我正在使用Eclipselink for JPA,并且有一个webapp,可以在配置的时间间隔内读取表格。数据库由工具外部修改以发布一些数据。现在我的webapp在一个Entity上创建一个getAll()并将结果作为一个列表获取。但是,每次我获得与第一个查询相同的结果列表。令人惊讶的是,新条目和删除的条目在结果列表中按预期反映出来。如果我更新条目,它仍然会获得原始/旧结果。
从我的搜索中,stackoverflow中的大多数答案都指向JPA级缓存,并且可以归纳为这些
<shared-cache-mode>NONE</shared-cache-mode>
@Cacheable(false)
em.getEntityManagerFactory().getCache().evictAll()
但是,这些解决方案都不适用于我的情况。我遇到的最接近的答案是this, which says that
会话缓存中已存在的任何ID都与已知实体匹配,而未根据数据库状态填充任何非ID。以前已知的实体根本不会从数据库中刷新。
虽然这是在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();
}
有人可以在Eclipselink的上下文中解释这个Session cache
,并解释为什么shared-cache
配置对此没有影响吗?事务是否透明地解决了这个问题(读取事务)?是否有优雅的解决方案/ JPA配置,而不是每次都在对象上刷新?
答案 0 :(得分:2)
从JPA 2.0开始,您可以使用查询提示来绕过或刷新缓存。
Query query = entitymanager.createQuery("select student FROM Student student");
query.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
Here是个很好的解释
答案 1 :(得分:1)
您提到的所有内容都指的是共享缓存,但JPA中有两个级别的缓存。共享缓存(第2级)和EntityManager管理实体缓存(第1级)。 EntityManagers用于表示事务工作空间。您应该在适当的时候获取新的Entitymanager实例,而不是使用单个实例,或者在其上调用em.clear()来释放资源。