我正在为 JPA 使用 Eclipselink,并且有一个 Web 应用程序可以在配置的时间间隔内读取表格。数据库通过工具在外部进行修改,发布一些数据。现在我的 webapp 在实体上创建一个 getAll() 并将结果作为列表获取。但是,每次我得到与第一个查询相同的结果列表。令人惊讶的是,新的条目和删除的条目都按预期反射(reflect)在结果列表中。如果我更新条目,它仍然会得到原始/旧结果。
根据我的搜索,stackoverflow中的大部分答案都指向JPA级别的缓存,可以归纳为这些
- 通过设置禁用共享缓存
<shared-cache-mode>NONE</shared-cache-mode>
- 可选地,使用
@Cacheable(false)
有选择地禁用实体缓存 - 通过执行
em.getEntityManagerFactory().getCache().evictAll()
清除缓存 - 有一些其他的/旧的/pre-JPA 2.0 和供应商特定的解决方案在 persistence.xml 中设置一些属性
但是,这些解决方案均不适用于我的情况。我遇到的最接近的答案是 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.
虽然这是在 Hibernate 的上下文中,但我在 Eclipselink 中遇到了同样的问题。因此,在对列表进行刷新后,我得到了预期的结果。
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();
}
谁能解释一下Session cache
在 Eclipselink 的上下文中,并解释为什么 shared-cache
配置对此没有影响?事务是否透明地解决了这个问题(读取事务)?是否有比每次都刷新对象更优雅的解决方案/JPA 配置?
最佳答案
从 JPA 2.0 开始,您可以使用查询提示来绕过或刷新缓存。
Query query = entitymanager.createQuery("select student FROM Student student");
query.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
Here是一个很好的解释
关于java - 为什么尽管禁用共享缓存仍需要 JPA 实体刷新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44422070/