<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    自由飛翔

    我在仰望,java之上

    統計

    留言簿(2)

    我關注的blog

    閱讀排行榜

    評論排行榜

    ssh集成中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無法對其進行控制,所以事務也不會起作用。
     

    3.OpenSessionInView 
    OpenSessionInView的主要功能是用來把一個Hibernate Session和一次完整的請求過程對應的線程相綁定。Open Session In View在request把session綁定到當前thread期間一直保持hibernate session在open狀態,使session在request的整個期間都可以使用,如在View層里PO也可以lazy loading數據,如 ${ company.employees }。當View 層邏輯完成后,才會通過Filter的doFilter方法或Interceptor的postHandle方法自動關閉session。 
    Java代碼  收藏代碼
    1. public class Group implements Serializable{   
    2.     private int id;   
    3.     private String name;   
    4.     private Set users;  
    5.          ...  
    6. }  

    在業務方法中加載Group對象并將其保存到HttpSession對象中 
    Java代碼  收藏代碼
    1. List groups = ht.find("from Group");  
    2. Group group = (Group)groups.get(0);  
    3. HttpSession session = ServletActionContext.getRequest().getSession();  
    4. session.setAttribute("group", group);  

    注意Group采用默認的延遲加載機制,即此時返回的只是一個Group代理對象, 
    在jsp頁面中顯示group對象的users屬性,如下: 

    Java代碼  收藏代碼
    1. <%    
    2.      Group group = (Group)session.getAttribute("group");  
    3.      out.println(group.getUsers());  
    4. %>   

    此時會拋出如下異常: 
    Java代碼  收藏代碼
    1. org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: entity.Group.users, no session or session was closed  

    延遲加載機制使得在業務方法執行結束之后僅僅返回Group的一個代理對象,在jsp頁面中使用到group對象的值時,才發出sql語句加載,但此時session已經關閉。解決方法是采用OpenSessionInView機制,在web.xml頁面中配置如下過濾器: 
    Java代碼  收藏代碼
    1. <filter>    
    2.    <filter-name>hibernateFilter</filter-name>   
    3.    <filter-class>   
    4. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter  
    5.    </filter-class>    
    6. </filter>  


    總結: 
    (1) 對于getSession(),getSession(false),getCurrentSession()以及getHibernateTemplate()方法而言,如果對其所在方法進行事務控制,那么可以確保在整個方法中只存在一個session,無論你執行了幾次CRUD操作,并且所打開的session會在事務結束時自動關閉。 
    (2) 必須對getSession(false)以及getCurrentSession()所在的方法進行事務控制(原因見上述分析) 
    (3) 如果沒有對getSession()以及getHibernateTemplate()所在方法進行事務控制,那么如果在方法中進行N次CRUD操作,就會打開N個session,即每次調用getSession()和getHibernateTemplate()方法都會打開新的session。這兩個方法的區別在于:getHibernateTemplate()方法結束時會自動關閉連接,而getSession()方法必須手動關閉。 
    (4) 如果在方法中采用SessionFactory的openSession()方法獲得連接進行操作,那么無法對其進行事務控制。 
    (5) 一般的開發中,通常采用getHibernateTemplate()方法進行數據庫操作, getHibernateTemplate()方法采用模板+回調的機制,進行數據庫操作很方便,可以查看(其中session的打開與關閉都是在doExecute方法中進行的):
     


    Gavin

    posted on 2012-03-23 15:33 GavinMiao 閱讀(4723) 評論(0)  編輯  收藏 所屬分類: spring

    主站蜘蛛池模板: 国产亚洲真人做受在线观看| 国产一区视频在线免费观看| 亚洲真人无码永久在线| 亚洲欧美自偷自拍另类视| 成人无遮挡裸免费视频在线观看| 亚洲精品国产肉丝袜久久| 亚洲精品在线免费观看| 亚洲人成在线影院| 无码免费一区二区三区免费播放| 亚洲中久无码永久在线观看同| 一区二区在线免费视频| 亚洲一区二区三区香蕉| 3344在线看片免费| 亚洲色图校园春色| 最近2019中文免费字幕| 麻豆亚洲AV成人无码久久精品| 亚洲不卡AV影片在线播放| jizz免费一区二区三区| 久久亚洲一区二区| 黄页网站在线观看免费高清| 亚洲中文字幕乱码一区| 波多野结衣视频在线免费观看| 香蕉免费在线视频| 亚洲美女精品视频| 女bbbbxxxx另类亚洲| 我要看WWW免费看插插视频| 亚洲视频无码高清在线| 亚洲国产成人久久一区久久| 国产色爽免费无码视频| 亚洲另类精品xxxx人妖| 免费在线观看中文字幕| 鲁丝片一区二区三区免费| 亚洲 欧洲 自拍 另类 校园| 亚洲午夜福利精品无码| 18女人水真多免费高清毛片| 亚洲国产精品嫩草影院 | 黄色片在线免费观看| 青娱乐在线视频免费观看| 亚洲AV电影院在线观看| 免费的一级片网站| 国产羞羞的视频在线观看免费|