对于JPA,我使用Eclipselink,并且有一个webapp,它在配置的时间间隔内读取表。数据库由一个工具进行外部修改,以发布某些数据。现在,我的webapp在实体上创建了一个getAll(),并以列表的形式获取结果。但是,每次我得到的结果列表与第一个查询的结果列表相同。令人惊讶的是,新条目和已删除条目按预期反映在结果列表中。如果我更新一个条目,它仍然会得到原始/旧的结果。
根据我的搜索,堆栈溢出点中的大多数答案都指向JPA级别的缓存,可以归纳为
<shared-cache-mode>NONE</shared-cache-mode>禁用共享缓存@Cacheable(false)选择性地禁用实体上的缓存em.getEntityManagerFactory().getCache().evictAll()删除缓存然而,这些解决方案都不适用于我的情况。我遇到的最接近的答案是这个,上面写着
会话缓存中已经存在的任何in都与已知实体相匹配,而不存在的任何in则基于数据库状态填充。以前已知的实体根本不会从数据库中刷新。
虽然这是在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配置比每次对对象进行刷新更好?
发布于 2017-06-10 04:14:54
从JPA2.0开始,您可以使用查询提示绕过或刷新缓存。
Query query = entitymanager.createQuery("select student FROM Student student");
query.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);这里是一个很好的解释
发布于 2017-06-08 16:01:11
您提到的所有内容都涉及到共享缓存,但是JPA中有两个级别的缓存。共享缓存(2级)和EntityManager管理实体缓存(1级)。EntityManagers用于表示事务性工作区。您应该在适当的地方获得新的Entitymanager实例,而不是对所有东西使用单个实例,或者调用它上的em.clear()来释放资源。
https://stackoverflow.com/questions/44422070
复制相似问题