我在長時間運行的對話(使用JPA /休眠和Seam 2.2)中第一級緩存存在問題。如何避免長時間運行Seam對話中的一級緩存
我們有一個搜索頁面,使用長時間運行的對話(需要一些Ajax交互,編輯模態等)。
問題是,當另一個用戶更改實體時,當用戶再次單擊搜索按鈕時,更改不會顯示。 見similar problem here
那麼長時間運行的對話實體從1級高速緩存加載過程中,在其它事務中做出的更改不會被加載,除非你手動調用每個實體刷新。
我試過使用CacheMode.IGNORE或CacheMode.REFRESH(通過hibernate查詢),但沒有解決問題,因爲它只處理二級緩存。
我可以看到選擇查詢被髮送到數據庫,但看起來Hibernate仍然使用第一級緩存中的緩存對象。
我試圖從我以前的搜索中驅逐實體,然後再進行新的搜索,然後運行,但是後來我遇到了有線問題,因爲會話中仍有對象指向現在被驅逐的實體。 您必須添加
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.EVICT,org.hibernate.annotations.CascadeType.REFRESH})
你的實體關係
但很容易錯過一個。
您也可以清除空洞會話,但這可能會導致LazyInitializationErrors。
是不是有辦法告訴JPA/Hibernate不要在查詢中使用第一級緩存?
編輯:有一個Good answer爲什麼它不起作用,但刷新每個實體的建議並不理想。我以前使用過這個,但問題在於,例如對於200個條目的列表,您可以爲數據庫生成200個單獨的負載,這使得它非常緩慢。 這200個條目中只有一兩個可能已經改變! 那麼你如何識別哪些實體已經改變!我猜如果你在每次更改的實體上使用時間戳,你可以使用它。只需記錄先前搜索的時間戳,然後搜索列表中已發生更改的實體。你怎麼看,那裏有更優雅的解決方案?
這是一個有趣的解決方案!當然,使用兩個實體管理器時,您不必使用一個entityManager加載的實體與另一個entityManager一起使用,那麼您需要非常小心。 – Ben 2013-04-04 14:19:18
我已經避免了上面的問題,只需遍歷列表並將其合併到「普通」entityManager中即可。我第一次運行查詢時,使用普通的對話範圍的entityManager。在隨後的搜索中,我使用事件範圍的entityManager,然後遍歷列表並在普通eventManager上合併實體。如果使用事件範圍化的entityManager並僅在後續搜索中進行合併,它會將合併開銷保持在最低水平。需要更多的測試,但看起來很有希望 – Ben 2013-04-04 15:30:16