hibernate session管理

1.通過getSession()方法獲得session進行操作 

Java代碼 

1.  public class Test  extends HibernateDaoSupport{  

2.       public void save(User user){  

3.          this.getSession().save(user);  

4.       }  

5.  }    


利用這種方式獲得的session在方法執行結束之後不會自動關閉連接,也就是說我們必須通過session.close()或者releaseSession(session)來手動進行關閉,否則會造成內存泄露或者連接耗盡等問題。手動關閉: 

Java代碼 

1.  public class Test  extends HibernateDaoSupport{  

2.       public void save(User user){  

3.          Session session = this.getSession();  

4.          session.save(user);  

5.          session.close();  

6.          // releaseSession(session);   

7.       }  

8.  }   


如果對上述方法進行事務控制,那麼spring框架會自動爲我們關閉session,此種情況下再執行上述代碼,會拋出如下異常:

Java代碼 

1.   org.springframework.orm.hibernate3.HibernateSystemException: Session is closed; nested exception is org.hibernate.SessionException: Session is closed  

2.  …  

3.  org.hibernate.SessionException: Session is closed  


提示session已經關閉。但是如果在代碼中通過releaseSession(session)的方法來關閉session,則不會拋出異常。releaseSession(session)方法的代碼如下: 

Java代碼 

1.  protected final void releaseSession(Session session) {  

2.      SessionFactoryUtils.releaseSession(session, getSessionFactory());  

3.  }  


也就是說它是通過SessionFactoryUtils的releaseSession方法來實現的: 

Java代碼 

1.  public static void releaseSession(   

2.       Session session,SessionFactory sessionFactory) {  

3.            if (session == null) {  

4.                return;  

5.            }  

6.            // Only close non-transactional Sessions.  

7.            if (!isSessionTransactional(session,sessionFactory))   {  

8.               closeSessionOrRegisterDeferredClose  (session, sessionFactory);  

9.            }  

10.     }  


可見它內部會先進行判斷。 

查看getSession()方法的源碼:
 

Java代碼 

1.  protected final Session getSession()  

2.          throws DataAccessResourceFailureException, IllegalStateException {  

3.    

4.          return getSession(this.hibernateTemplate.isAllowCreate());  

5.  }  


getSession()方法內部通過它的一個重載方法getSession(boolean allowCreate )來實現,變量allowCreate是HibernateTemplate中的變量,默認值爲true,也就是創建一個新的session。如果我們調用getSession(false)來獲得session,那麼必須對其進行事務控制,原因是:(spring文檔)

Java代碼 

1.  protected  final  org.hibernate.Session  getSession()   

2.  throws DataAccessResourceFailureException,   IllegalStateException    

3.    

4.  Get a Hibernate Session, either from the current transaction or a new one. The latter is only allowed if the "allowCreate" setting of this bean's HibernateTemplate is true.   


也就是說,getSession()方法從當前事務或者一個新的事務中獲得session,如果想從一個新的事務中獲得session(也就意味着當其不存在事務控制),則必須使HibernateTemplate中的allowCreate變量的值爲”true”,而現在設置allowCreate變量的值爲”false”就意味着無法從新的事務中獲得session,也就是隻能從當前事務中獲取,所以必須對當前方法進行事務控制,否則會拋出如下異常: 

Java代碼 

1.  java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here ...  


同時,如果對getSession()所在的方法進行事務控制,那麼類似如下的代碼: 

Java代碼 

1.  Session session = null;  

2.  for(int m =0;m<5;m++){  

3.      Admin admin = new Admin();  

4.      admin.setName("test");  

5.      admin.setPassword("098");     

6.      session = this.getSession();  

7.      session.save(admin);  

8.  }  


只會打開一個session,因爲事務控制必須確保是同一個連接,spring會確保在整個相關方法中只存在一個session。Spring在方法開始時會打開一個session(即使進行事務控制的方法內部不執行數據庫操作),之後在請求session時,如果在事務中存在一個未commit的session就返回,以此確保同一個session。 

2.getCurrentSession()與openSession() 
getCurrentSession()與openSession()方法通過Hibernate的SessionFactory獲得,兩者的區別網上有很多文章已經介紹過,即:

Java代碼 

1.  ①getCurrentSession創建的session會和綁定到當前線程,而openSession不會。   

2.  ②getCurrentSession創建的線程會在事務回滾或事物提交後自動關閉,而openSession必須手動關閉  



對於getCurrentSession()方法: 
       (1)其所在方法必須進行事務控制 
       (2)Session在第一次被使用的時候,或者第一次調用getCurrentSession()的時候,其生命週期就開始。然後它被Hibernate綁定到當前線程。當事務結束的時候,不管是提交還是回滾,Hibernate也會把Session從當前線程剝離,並且關閉它。假若你再次調用getCurrentSession(),你會得到一個新的Session,並且開始一個新的工作單元。     
   
對於openSession()方法: 
        這個方法一般在spring與Hibernate的集成中不直接使用,它就是打開一個session,並且這個session與上下文無關,如果對其所在方法進行事務控制,會發現不起作用,原因就是前面提到的,事務控制必須確保是同一個連接,而openSession()打開的session與上下文無關。這個方法與getSession(),getCurrentSession()以及getHibernateTemplate()等方法的區別在於:後面的幾個方法spring可以對其進行控制,如果對它們所在的方法進行事務控制,spring可以確保是同一個連接,而openSession()方法,spring無法對其進行控制,所以事務也不會起作用。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章