Invalidating JPA EntityManager session
A project I am working on uses Spring 2.5 & JPA with Hibernate as a provider.
My DAO classes extend JpaDaoSupport, so I get my JpaTemplate using the getJpaTemplate() method.
The back-end database can get changed either by my application, or a third-party application.
When a third-party application changes the database (mostly configuration data changes), I need to provide the user of my application a way to invalidate all JPA sessions and reload the new data (i.e. invalidate all the hibernate sessions in the background). This needs to be "seen" by all concurrent users of my application.
How can I do this?
Solution 1:
There are two levels of caches:
-
1st level is the EntityManager's own cache.
You can either
refresh
on one entity and it will be reloaded form the database, or you canclear
the entity manager itself, in which case all entities are removed from the cache. There is no way with JPA to evict only one specific entity from the cache. Depending on the implementation you use, you can do this, e.g. Hibernate'sevict
method. -
2nd level caching is the global cache.
JPA 1.0 did not provide support for 2nd level cache. You need then to rely on the underlying specific implementation, or to disable it. JPA 2.0 will address this issue with
@Cache
annotation and the cache API. You can clear the 2nd level cache using Hibernate-specific API, e.g.SessionFactory.evict(...)
.- Unerstanding Hibernate 2nd level cache
Advanced issues with caching are:
-
Query cache
Result of certain queries can be cached. Again not support for it in JPA 1.0, but most implementation have ways to specify which query will be cached and how.
- Understanding the query cache in Hibernate
-
Clustering
Then comes also the tedious problem of synchronizing caches between nodes in a cluster. In this case, this mostly depend on the caching technology used, e.g. JBoss cache.
Your question is still somehow generic and the answer will depend on what you are exactly doing.
I worked on a system were many updates would be done without going through hibernate, and we finally disabled the 2nd level cache.
But you could also keep track of all opened sessions, and when necessary evict all 1st level cache of all opened session, plus the 2nd level cache. You would still need to manage synchronization yourself, but I imagine it's possible.
Solution 2:
From an architectural point of view it is not a very good idea to let some other application bypass all your business logic and modify persistent data. It makes the ground beneath the feet of your application shaky in a lot of ways :)
Wouldn't it be a good idea to integrate with this other system in a more elegant way, for example by message processing or batch processing. Spring has great support for both of them.