2012-01-23 52 views
14

我無法理解使用Hibernate回調方法的優點,是否有任何優勢或具體用例我們應該去做。使用Hibernate回調的優點?

public List findRecentRequests(final int offset, final int length) 
{ 
    List list = getHibernateTemplate().executeFind(new HibernateCallback() 
    { 
     public Object doInHibernate(Session session) throws HibernateException 
     { 
      Query q = session.createQuery(FIND_RECENT_REQUESTS); 
      q.setFirstResult(offset); 
      q.setMaxResults(length); 
      return q.list(); 
     } 
    }); 
    return list; 
} 

另外一個更重要的問題是,HibernateCallback方法在查詢返回值後每次關閉會話嗎?我有使用情況,每次刷新狀態頁面時都會多次調用此函數,每次打開會話和查詢數據庫時都會調用該函數,或者將查詢結果存儲在內存中,然後每次調用此函數時都會彈出結果從記憶裏。

我已閱讀(Reference):

彈簧HibernateTemplate.execute()默認完成後,關閉所有打開的會話。當延遲初始化使用可能會得到像下面這樣

org.hibernate.LazyInitializationException LazyInitializationException中:無法初始化代理 - 沒有會話

相關文檔部分的任何引用將高度讚賞。

更新:

在我的情況下,使用EJB事務和將其設置爲「支持」,我相信在爲交易設置爲支持這種情況下,它是可選的,所以每次新的會話將被創建我和hibernate會查詢數據庫以獲得結果,所以這就是瓶頸,這是否是一個正確的假設?

+0

您應該在您打開會話的數據訪問層返回之前初始化懶惰集合。或者使用'OpenSessionInViewFilter' – millimoose

+0

@Inddial:如果你能用一個例子來詳細說明,我會非常感激。 – Rachel

+0

Hibernate文檔已經處理[初始化集合和代理](http://docs.jboss.org/hibernate/core/4.0/manual/en-US/html/performance.html#performance-fetching-initialization)。 Spring還提供了[「在視圖中打開會話過濾器」的實現](http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter .html)由Hibernate文檔提到。 – millimoose

回答

18

要說明你爲什麼要使用HibernateCallback。簡短的回答 - 它允許您訪問當前的事務綁定會話,以執行更復雜的休眠功能。大多數情況下,HibernateTemplate上的簡單方法已足夠,但有時您需要下載到Session

這個難題有兩個部分。

第一個是通過使用PlatformTransactionManager/TransactionTemplate@Transactional註釋來定義的交易範圍。有關更多信息,請參閱spring docs/google。

第二個是當你在一個交易中HibernateTemplate會使用一點魔力與當前交易進行交互。

因此,像hibernateTemplate.save()這樣的簡單操作將參與交易。像你的例子一樣更復雜也將參與交易。事實上,hTemplate上的任何方法都會參與其中。

所以知道你什麼時候做的會話中獲取關閉

  • 如果您正在使用事務明確,見第一點以上,然後在交易範圍內關閉該交易將被提交,該會議將是問題關閉。
  • 如果沒有交易,每當您調用HibernateTemplate方法時,spring會爲您創建一個會話,並在之後立即關閉它。這不是首選方法,因爲除非你做的事情非常簡單,否則結果將從會話中分離出來,並且您將得到LazyInit異常。

上述第二種情況下需要注意的重要一點是沒有明確的交易。你處於連接的自動提交模式的控制之下,所以你可以在回調,保存,保存和拋出異常的時候這樣做。第一次保存可能已經發生,沒有交易就沒有保證。

我的建議,當做任何更新,使用交易。

如果所有的交易資料都是新的,請查看交易章節的spring文檔。

+0

+1瞭解詳細信息。 – Rachel

+0

在我的情況下,我使用ejb事務並將其設置爲「支持」,並且我相信在事務被設置爲支持的情況下,它是可選的,所以每次創建新會話時,hibernate都會查詢數據庫以獲取結果,所以這就是我有瓶頸,那會是一個正確的假設嗎? – Rachel

+0

對不起,我沒有關注瓶頸問題,你能改說嗎? –

6

如果你正在使用Spring,你應該在你的Repository或Service層使用declarative transaction management來透明地處理這個問題。 PlatformTransactionManager實現將爲給定的持久性提供程序執行適當的操作。

在你離開數據訪問代碼之後,依賴懶惰集合被初始化被認爲是不好的做法 - 它通常意味着你的應用程序的控制器/視圖層中有一些業務邏輯應該被移動到服務層。