Hibernate 如何在长时间运行的Seam对话中避免一级缓存

Hibernate 如何在长时间运行的Seam对话中避免一级缓存,hibernate,caching,jpa,seam,Hibernate,Caching,Jpa,Seam,我在长时间运行的对话(使用JPA/Hibernate和Seam 2.2)中遇到了一个一级缓存问题 我们有一个搜索页面,它使用长时间运行的对话(一些ajax交互、模态编辑等需要) 问题是,当另一个用户更改实体时,当用户再次单击搜索按钮时,这些更改不会显示出来。 看 因此,在长时间运行的会话中,从一级缓存加载实体,除非手动调用每个实体上的刷新,否则不会加载在其他事务中所做的更改 我尝试使用CacheMode.IGNORE或CacheMode.REFRESH(通过hibernate查询),但这并不能解

我在长时间运行的对话(使用JPA/Hibernate和Seam 2.2)中遇到了一个一级缓存问题

我们有一个搜索页面,它使用长时间运行的对话(一些ajax交互、模态编辑等需要)

问题是,当另一个用户更改实体时,当用户再次单击搜索按钮时,这些更改不会显示出来。 看

因此,在长时间运行的会话中,从一级缓存加载实体,除非手动调用每个实体上的刷新,否则不会加载在其他事务中所做的更改

我尝试使用CacheMode.IGNORE或CacheMode.REFRESH(通过hibernate查询),但这并不能解决问题,因为它只处理二级缓存

我可以看到select查询被发送到数据库,但Hibernate似乎仍在使用一级缓存中的缓存对象

在进行新的搜索之前,我曾尝试从以前的搜索中逐出实体,但效果不错,但后来我遇到了有线问题,因为会话中仍有对象指向现在逐出的实体。 你必须加上

@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.EVICT,org.hibernate.annotations.CascadeType.REFRESH})
你的实体关系,但很容易错过一个

您也可以清除hole会话,但这可能会导致LazyInitialization错误

有没有办法告诉JPA/Hibernate不要在查询中使用一级缓存

编辑:有一个原因是它不起作用,但刷新每个实体的建议并不理想。我以前使用过这个,但问题是,例如,对于包含200个条目的列表,您会向数据库生成200个单独的加载,这使得加载速度非常慢。 在这200个条目中,只有一两个可能发生了变化!
那么,您如何确定哪些实体已更改!我想,如果您在每次更改时更新的实体上使用时间戳,您可以使用它。只需记录上一次搜索的时间戳,然后搜索列表中自那时以来已更改的实体。你觉得还有什么更优雅的解决方案吗

解决方法是在事件范围中定义一个单独的持久性上下文工厂,并将其用于查询。在
components.xml
中:

<persistence:managed-persistence-context scope="event" auto-create="true" 
    entity-manager-factory="#{yourfactory}" name="eventScopedEM" />

这是一个有趣的解决方案!当然,在使用两个entityManager时需要非常小心,不要将一个entityManager加载的实体与另一个entityManager一起使用。我通过简单地迭代列表并将其合并到“普通”entityManager中,避免了上述问题。第一次运行查询时,我使用普通会话范围的entityManager。在随后的搜索中,我使用事件范围的entityManager,然后在列表上迭代并合并普通eventManager上的实体。如果使用事件范围的entityManager,并且仅在后续搜索时进行合并,则可以将合并的开销保持在最低限度。需要更多的测试,但看起来很有希望
<framework:entity-query entityManager="#{eventScopedEM}">
    <framework:ejbql>from MyEntity</framework:ejbql>
    ...
</framework:entity-query>