我有使用JPA的Web应用程序。这个实体管理器保留了大量的实体,突然间我从另一侧更新了数据库。我使用 MySQL ,我使用 PhpMyAdmin 并更改了一些行。
如何告诉实体经理重新同步,例如忘记缓存中的所有entites?
我知道有refresh(Object)
方法,但是有可能如何做refreshAll()
或其中的结果吗?
这肯定是昂贵的操作,但是如果必须这样做的话。
答案 0 :(得分:35)
entityManager.getEntityManagerFactory().getCache().evictAll()
Refresh
因为修改您的对象而有所不同。这一行只有empty the cache
,因此如果您获取在实体管理器外部更改的对象,它将执行实际的数据库查询,而不是使用过时的cached
值。
答案 1 :(得分:7)
我有一个类似的问题,上面的evictAll()
行为我工作。
或者,实体类的@Cache
注释也可以工作,并且能够控制缓存参数:
@Cache(coordinationType=CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS)
请参阅:http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching
答案 2 :(得分:3)
好吧,对于那些尝试添加 factory.getCache()。evictAll(); 并且不起作用并且使用JPA + Hibernate来刷新查询的人(比如我)将提示 org.hibernate.cacheMode 添加到 IGNORE 。例如:
em.createNamedQuery("SomeEntity.SomeNamedQuery")
.setHint("org.hibernate.cacheMode", "IGNORE")
.getResultList();
答案 3 :(得分:2)
cache.evictAll对我不起作用。因此,为了检索从另一个应用程序推送的数据,我执行:
em.getTransaction().begin();
em.getTransaction().commit();
之后,我的查询查询检索刷新的数据。我不知道它是否是非常安全的解决方案,但它运作正常。
答案 4 :(得分:2)
如果您使用的是EclipseLink而不是Hibernate,则提示是:
em.createNamedQuery("SomeEntity.SomeNamedQuery")
.setHint(QueryHints.REFRESH, true)
.getResultList();
答案 5 :(得分:0)
当您将对象读入EntityManager时,它将成为持久化上下文的一部分,并且同一个对象将保留在EntityManager中,直到您清除()它并获取新的EntityManager。 因此,如果更新数据库,除非您在对象上调用refresh()或清除()EntityManager,否则EntityManager将看不到更改。这与共享缓存(L2)或持久性上下文(L1)无关。如果您还使用共享缓存并直接更新数据库,那么您的共享缓存将过时。您需要刷新()对象,或将其标记为无效,以便在下次查询时刷新。
代码必须遵循这样的方式。 分离 REFRESH 合并 FLUSH