29

I have web application using JPA. This entity manager keeps bunch of entites and suddenly I update the database from other side. I use MySQL and I use PhpMyAdmin and change some row.

How to tell entity manager to re-synchronize, e.g. to forgot all the entites in cache?

I know there is refresh(Object) method, but is there any possibility how to do refreshAll() or something what results in this?

It is sure this is expensive operation but if it has to be done.

YCF_L
  • 49,027
  • 13
  • 75
  • 115
zdenda.online
  • 2,171
  • 2
  • 19
  • 43

6 Answers6

40
entityManager.getEntityManagerFactory().getCache().evictAll()

Refresh is something different since it modifies your object. This line will just empty the cache, so if you fetch objects changed outside the entity manager, it will do an actual database query instead of using the outdated cached value.

Rasmus Franke
  • 4,184
  • 8
  • 42
  • 61
  • 5
    I know this is a couple years old, but I wanted to throw my two cents in. I'm not exactly sure this can be called the answer. evictAll() works in the scenario where you want the new data being persisted/merged to ignore what's cached and force update/insert the database. However, evictAll() does NOT work (at least for me) in the scenario where first the backend database changes a value and THEN you expect the change to show up when pulled from the datastore. In my experience, the cache still overrides what was changed in the backend. – Jason Washo Aug 01 '16 at 19:51
  • @JasonWasho, do you have a solution to cache still overriding issue? – Downhillski Apr 18 '18 at 19:38
  • 3
    entityManager.clear() empties the persistence context. This causes the entity to be fetched again from database. – Orçun Çolak Dec 10 '19 at 11:41
8

I had a similar issue and the evictAll() line above worked for me.

Alternatively, the @Cache annotation on the entity class worked too, with the benefit of being able to control caching parameters:

@Cache(coordinationType=CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS)

See: http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching

Code Maverick
  • 19,231
  • 10
  • 57
  • 111
Arnold
  • 81
  • 1
  • 2
4

If you are using EclipseLink instead of Hibernate the hint is:

em.createNamedQuery("SomeEntity.SomeNamedQuery")
.setHint(QueryHints.REFRESH, true)
.getResultList();
Ivan
  • 41
  • 2
3

Well, for some people (like me) that tried to add factory.getCache().evictAll(); and doesn't work, and are used JPA + Hibernate, to refresh a query add the hint org.hibernate.cacheMode to IGNORE. Example:

em.createNamedQuery("SomeEntity.SomeNamedQuery")
  .setHint("org.hibernate.cacheMode", "IGNORE")
  .getResultList();
futbolsalas15
  • 163
  • 1
  • 7
2

cache.evictAll is not working for me. So to retrieve data pushed from another app, I peform :

em.getTransaction().begin();
em.getTransaction().commit();

After that, my find query retrieves refreshed data. I don't know if it's very safe solution but it works properly.

William D.
  • 46
  • 1
1

When you read an object into an EntityManager, it becomes part of the persistence context, and the same object will remain in the EntityManager until you either clear() it and get a new EntityManager. So if you update the database, the EntityManager will not see the change unless you call refresh() on the object, or clear() the EntityManager. This has nothing to do with the shared cache (L2) or the persistence context (L1). If you also also using a shared cache, and updating the database directly, then your shared cache will be out of date. You need to refresh() the object, or mark it as invalid to be refreshed the next time it is queried.

Code must follow the way like. DETACH REFRESH MERGE FLUSH

rahulnikhare
  • 1,012
  • 12
  • 20
  • But if you try to refresh a detached entity, you will get a "java.lang.IllegalArgumentException: Entity not managed". So you have to detach, merge, refresh instead? – mavok May 18 '20 at 06:58