解決Hibernate懶載入的4種方式
本文總結了我在學習hibernate的過程中,解決hibernate懶載入問題的四種方式。
懶載入簡述:當我們查詢一個物件的時候,在預設情況下,返回的只是該物件的代理物件,當用戶去使用該物件的屬性時,才會向資料庫再一次發出查詢語句。
例如,有一個物件是Employee,還有一個物件是Department。顯然,對於Employee相對Department來說,是多對一的關係;而對於Department相對Employee來說,是一對多的關係。當我們查詢Employee物件的時候,如果希望通過employee物件的屬性department查詢到所對應的Department,那麼是會丟擲異常的。這是因為懶載入的存在,在session關閉之後,hibernate又向資料庫發出一次請求,結果就丟擲異常了。
下面總結的是解決這個問題的四種方式:
1.顯式初始化(在查詢方法內部)
要查詢某員工屬於哪個部門的時候,需要對Department進行預先查詢
使用語句
Hibernate.initialize(Department.class);
2.修改物件關係檔案,將lazy 改寫lazy = false,即關閉懶載入
以上兩種方法,確實可以解決問題,但是缺點是無論後面是否使用該物件,hibernate都會向資料庫發出SQL語句請求資料,造成不必要的效能浪費。
3.使用過濾器(web專案)
①獲取session的方式必須使用getCurrentSession
②特殊的關閉session方式
public void doFilter(ServletRequest request, ServletResponse response, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub Session session = null; Transaction tx = null; try { session = HibernateUtil.getCurrentSession(); tx = session.beginTransaction(); arg2.doFilter(request, response);//請求一直在走 tx.commit(); } catch (Exception e) { // TODO: handle exception if(tx != null){ tx.rollback(); } }finally{ //特殊的關閉方式 HibernateUtil.closeCurrentSession(); } }
4.在SSH框架中,使用spring提供的openSessionView
其原理和第三種方法中使用Filter類似,只不過這個filter是spring提供的。使用時只需要在web.xml檔案配置如下:
<!-- 使用spring解決懶載入問題 --> <filter> <filter-name>OpenSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>OpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
第3和第4中方法也能解決懶載入的問題,其中第4種方法也是目前使用較多的。但是這兩種方法也是有缺點的,缺點就是延長了session關閉的時間,session的生命週期變長。沒有使用該方法之前,session是在查詢完資料之後,就被關閉了;而現在,session的關閉是在一次web請求的最後才關閉。