java - 为什么尽管禁用共享缓存仍需要 JPA 实体刷新?

标签 java hibernate jpa eclipselink jpa-2.0

我正在为 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/

相关文章:

java - 通过 JNDI 引用设置 Hibernate 的默认架构

java - 玩!框架——ORM

java - 生成长度为 10 的唯一、随机字母数字主键

java - 如何使用 JPA (Hibernate) 创建与同一实体的关系?

java - Intellij, "contentPane cannot be set to null"使用 Swing 设计器

java - 按一对多关联计数排序的 Hibernate 标准

java - 使用 Selenium WebDriver 和 Java 切换选项卡

Java:将 StreamResult 转换为 DOM

java - 尽管延迟初始化还是热切加载?

java - 在 Spring 规范中渴望获取