Reputation: 753
I'm using Eclipselink for JPA, and has a webapp which reads the tables in a configured interval. The database is modified externally by a tool to publish some data. Now my webapp makes a getAll() on an Entity and gets the result as a list. However, each time I get the same result list as it was from the first query. Surprisingly, new entries and deleted entries are reflected as expected in the result list. If I update an entry it still gets the original/old result.
From my search, most of the answers in stackoverflow points to JPA level cache, and can be summarized to these
<shared-cache-mode>NONE</shared-cache-mode>
@Cacheable(false)
em.getEntityManagerFactory().getCache().evictAll()
However, none of these solutions work in my case. The closest answers I came across was this, which says that
Any IDs that are already present in the Session cache are matched up to known entities, while any IDs that are not are populated based on database state. The previously known entities are not refreshed from the database at all.
Although this is in the context of Hibernate, I hit the same issue in Eclipselink. So after introducing a refresh on the list I get the expected result.
T objects = getAll();
for (T objects : object)
em.refresh(object)
List<T> getAll() {
EntityManager em = entityManagerFactory.createEntityManager();
return em.createQuery(em.getCriteriaBuilder().createQuery(type)).getResultList();
}
Can someone explain this Session cache
in the context of Eclipselink, and explain why shared-cache
configuration has no impact on this ? Does a transaction transparently solve this problem (read transaction)? Is there an elegant solution/JPA configuration than doing refresh on object each time ?
Upvotes: 1
Views: 2837
Reputation: 544
From JPA 2.0 onwards, you can use query hints to bypass or refresh the cache.
Query query = entitymanager.createQuery("select student FROM Student student");
query.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
Here is a nice explanation
Upvotes: 2
Reputation: 21190
Everything you've mentioned refers to the shared cache, but there are 2 levels of caching in JPA. The shared cache (2nd level) and EntityManager managed entity cache (1st level). EntityManagers are meant to represent transactional workspaces. You should obtain new Entitymanager instances where appropriate rather than use a single one for everything, or call em.clear() on it to release resources.
Upvotes: 1