0

I seem to be having an issue clearing hibernate cache, no matter what I try to clear any cache, if I call my DAO.findAll(), I still get several results. All of which no longer exist in my local database. Some results haven't existed for weeks, but still somehow show up. This has been driving me nuts for a few days, and I have searched pretty much everything to see if I could find something I haven't tried yet. So here is my basic setup

  • hibernate core 3.3
  • hibernate annotations 3.4
  • hibernate commons annotations 3.4
  • spring 3.0.7
  • persistance api 1.0
  • junit 4.8.2

I don't really have the option to update versions right now, so I need to find a solution within my current version stack. Everything is working with the setup, but for testing my DAO I can't seem to clear out some old cache. It's like its getting read from a flat file somewhere and won't go away! lol.. grrrr... I'm hoping someone can see the obvious answer or lead me in the right direction.. I know the code examples below are not full 100% classes, but I've taken out what I think is most pertinent for this question, if more is needed to help clarify, please lemme know!

Just a little background, I had been playing with the Junit test to update the query, but I found I was getting cached result back, not results from my actual query, so since then I've been trying to figure out some way where I can clear this infamous cache, here's a few links I've looked further into but which hasn't seemed to work so far dealing with 1st and 2nd level cache..

Need more reputation points for the remaining list of links I've checked out.. :(

A lot of what I've seen has been geared towards JPA 2, and/or hibernate itself. But not too much when it comes to JPA 1 with hibernate.. I think part of the problem is if you look at my junit test setup below, I commented out the complete() method which would rollback any inserts as part of the tests, I wanted to allow the data to stay in the database so I commented that out, but it seems like I orphaned a session or something and now I can't remove those cached records, even though I manually deleted the original entries from the database.

Here is basically what I have going on...

persistence xml

<persistence-unit name="ServicePersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

<class>com.pkg.service.model.MyService</class>

    <properties>
        <property name="hibernate.connection.url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>
        <property name="hibernate.hbm2ddl.auto" value="validate"/>
        <property name="hibernate.connection.username" value="xxxx"/>
        <property name="hibernate.connection.password" value="xxxx"/>
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.connection.autocommit" value="false"/>
    </properties>
</persistence-unit>

Context XML

<context:component-scan base-package="com.pkg.service.dao" />
<context:annotation-config/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceXmlLocation" value="META-INF/jpa-persistence.xml" />
    <property name="persistenceUnitName" value="ServicePersistenceUnit" />
</bean>

<bean id="entityManager" class="javax.persistence.EntityManager" factory-bean="entityManagerFactory" factory-method="createEntityManager" />

<bean id="ServiceDaoImpl" class="com.pkg.service.dao.impl.ServiceDaoImpl">
    <property name="entityManager" ref="entityManager"/>
</bean>

ServiceDAOImpl

@Repository("serviceDao")
public class ServiceDaoImpl extends AbstractJpaDAO<String, StoredService> implements ServiceDao {

@Autowired
EntityManagerFactory entityManagerFactory;

@PostConstruct
public void init() {
    super.setEntityManagerFactory(entityManagerFactory);
}

public EntityManagerFactory getEntityManagerFactory() {
    return entityManagerFactory;
}

@Override
@Transactional
public void save(StoredService storedService) {
    getJpaTemplate().persist(storedService);
}

@Override
@Transactional(readOnly = true)
public Collection<MyService> findServices(final QueryParams queryParams) throws IllegalArgumentException {
    List<MyService> result = getJpaTemplate().execute(new JpaCallback<List<MyService>>() {
    @Override
    @SuppressWarnings("unchecked")
        public List<MyService> doInJpa(final EntityManager em) throws PersistenceException {
            Query query = ServiceQueryFactory.createQueryWithParams(queryParams, em); 
            return query.getResultList();
        }
    });
    return result;
}

}

MyService (Model Obj)

@Entity
@Table(name = "MYSERVICE")
@SqlResultSetMapping(
    name = ServiceQueryHelper.MY_SERVICE_MAPPING, 
    entities = { 
        @EntityResult(
            entityClass = com.pkg.service.model.MyService.class, 
            fields = {
                @FieldResult(name = "id",       column = "id"), 
                @FieldResult(name = "serviceName",  column = "servicename"),
                @FieldResult(name = "serviceId",    column = "serviceid")
            }
        ) 
    }
)
public class MyService implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(
        name = "MYSERVICE_SEQ", 
        sequenceName = "MYSERVICE_SEQ",   
        allocationSize = 1)
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE, 
        generator = "MYSERVICE_SEQ")
    private long id;

    private String serviceName;

    private long serviceId;

    //GETTERS AND SETTERS...

}

Helper Classes

public class ServiceQueryHelper {

    public static final String MY_SERVICE_MAPPING = "my_service_mapping";
    public static final String MY_QUERY = "This is my select query";

}

public class ServiceQueryFactory {

    public static Query createQueryWithParams(QueryParams queryParams, EntityManager em){

        //QueryParams aren't used right now, working on clearing the cache first :)

        Query query = em.createNativeQuery(ServiceQueryHelper.MY_QUERY, ServiceQueryHelper.MY_SERVICE_MAPPING);
        return query;

    }

}

And finally the test class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/persistence-test.xml" })
public class ServiceDaoImplTest {

    @Resource
    private ServiceDaoImpl ServiceDaoImpl;

    @Resource(name = "entityManager")
    private EntityManager entityManager;


    @Before
    public void init() {
        serviceDaoImpl.setEntityManager(entityManager);
        entityManager.getTransaction().begin();
        //setupTestData();
    }   

    @After
    public void complete() {
        entityManager.flush();
        entityManager.getTransaction().rollback();
    }

    @Test
    public void shouldReturnNoServices() {

        //There are no services in the database right now...
        Collection<MyService> services = ServiceDaoImpl.findAll();

        //This fails with services that seem to be in cache
        assertEquals("Should be empty", 0, services.size());

    }

}
Community
  • 1
  • 1
byte-crunch
  • 271
  • 2
  • 13

1 Answers1

0

As odd as it seems, it turns out the issues I was seeing was a result of having SQL Developer Lite open, and logged into the database I was testing through Junit. For anyone else that runs into an issue similar to this, I first noticed the conflict when running a query that had several LAST_VALUE functions applied to essentially "role up" data and be able to select a row that had an accumulation of the records I was interested in.

I didn't connect the two as having a conflict initially and rather was focusing on what seemed like a caching issue, but no matter what I tried to clear cache through first level, second level, and query cache, I always got the same "old" results back from the database/hibernate, not the data I was expecting to see through the new query.. and oddly enough the database didn't have any data in it either.

Another strange thing I noticed was when I tired to run a native query to DELETE FROM TableName to see if I could somehow clear the results I was seeing, it would just sit and hang as if it were in a deadlock. The only thing I could think of that could be potentially causing a conflict was the database tool and having that table in view. Once I closed that, all my attempts to delete executed, and once I cleared the entity manager again, my issue cleared up. So at the end of the day it was a conflict with my SQL Developer tool being open while I was trying to manipulate the data in my junit tests.

byte-crunch
  • 271
  • 2
  • 13