2012-06-06 69 views
3

我在ehcache中存儲hibernate實體。當調用Facade層來檢索實體時,我的攔截器將調用該方法並對其進行緩存。下次調用同一個方法時,實體將從緩存中返回。這一切工作正常。從ehcache加載hibernate對象時出現Lazyinitialization異常

我的實體有一些屬性(對象或關聯實體),它們被定義爲FetchType.Lazy。它是這樣的,

@JoinColumn(name = "inventory_item_oid", referencedColumnName = "inventory_item_oid") 
@ManyToOne(fetch = FetchType.LAZY) 
private InventoryItem inventoryItem; 

因此,並非所有屬性加載。需要庫存物品時調用。這個調用拋出了LazyInitialization Exception。

由於我的緩存值存活了一天,因此可以在它過期之前調用任意次數。

其中一個調用拋出上述異常。

我發現使用長久的休眠會話,我可以解決這個問題。但它不工作,因爲我是基於請求/響應的應用程序。

還有一種方法,我需要檢查如果InventoryItem是否爲null或在訪問其屬性之前,如果它爲空,那麼我需要單獨獲取該值並將其附加到父級。這似乎是好事,但需要很多工作,因爲我有很多實體。

我想知道是否有任何其他方式可以獲取定義爲懶惰的對象。

回答

1

您不應該自己在EHCache中緩存實體。相反,您應該配置Hibernate使用二級緩存,並使用EHCache作爲其實施。

最終結果將是相同的:您的實體將被緩存,並且您將往返存入數據庫。但是通過使用二級緩存,一切都將是透明的:您將從會話中加載實體,Hibernate將自動將它們存儲在緩存中。如果你從會話中重新加載它們,Hibernate將從緩存中獲取它們。如果你更新實體,它將被從緩存中刪除,以確保下次重新加載新的副本。

與您的手工解決方案的另一個巨大的區別是,休眠將返回附加實體。因此,如果你只是調用cachedEntity.getNonCachedEntity(),Hibernate將惰性加載非緩存實體,就像完全沒有緩存一樣。

實體來自數據庫還是來自二級緩存不會改變任何內容:如果某個屬性延遲加載,並且一旦會話關閉就訪問此屬性,那麼lazy屬性必須是在會議結束前初始化。

致電Hibernate.initialize(foo.getInventotyItem())初始化它。

更多的信息在Hibernate documentation

+0

「,並且如果在會話關閉後訪問此屬性,那麼必須在會話關閉之前初始化該屬性。我如何知道首先檢索該對象將在會話之外使用?您的建議就像每次初始化檢索的緩存對象,以確保完全打破使用延遲屬性的優勢。 –

+0

您不需要在檢索時初始化惰性屬性。如果您打算在之後訪問會話,則必須確保在關閉會話之前對其進行了初始化。解決這個問題的最簡單方法是在會話關閉後不訪問任何屬性(例如,只有在完成使用實體後,使用開放會話視圖過濾器才能關閉它),或者避免在會話關閉後使用實體(例如通過將實體轉換爲DTO) –

+0

好的,這是一個測試。我第一次調用存儲庫方法,並使用惰性非初始化道具對其結果進行緩存。線程結束。從另一個線程我調用相同的方法,並嘗試讀取這些道具時得到懶惰異常。爲什麼我需要做一些額外的工作(即明確開放一個會話),而不是委託給緩存軟件?可能會有更多的決定與緩存配置? –