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..
- http://java.dzone.com/tips/clearing-hibernate-second-leve
- Hibernate first level cache - does it Sync?
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());
}
}