Hibernate中的openSession(),getSession() 和 getCurrentSession() 的區別

開發中,使用MyEclipse自動生成的Hibernate DAO類中在對session的獲取中,都使用的getSession(MyEclipse8.5之前的版本都是如此)。

首先要說明一下這3個方法:

1、openSession 和 getCurrentSession這兩個方法是 Hibernate中的sessionFactory中的方法。要獲取session只能通過這兩個方法獲取。

2、getSession這個方法是使用MyEclipse的Hibernate工具時自動生成的方法。進入方法裏查看:

 public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();


if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}


        return session;
    }

很明顯,Myeclipse使用的是openSession。所以上述的3個方法,其實也就是openSession和getCurrentSession的區別。

這裏簡單說明一下openSession 和 getCurrentSession這兩個方法的區別。很容易看出來,openSession每次都是創建一個新的session,而getCurrentSession會查看,如果當前上下文中已經有Session,則直接使用原有的,否則會創建一個新的session。

當然這樣說並不是很形象。很多人會理解爲,後面一個只是前面的略微優化而已,每次都打開新的也不會出錯。當然這樣理解並沒有完全錯誤,其實這裏的Session使用上沒有很大的區別,區別是在於使用openSession時,如果涉及到對數據庫的數據的修改(增、刪、改),在事務提交之後,session必須手動關閉(session.close()),否則會出錯,一般是數據已經保存進數據庫,但使用Hibernate再次查詢數據時並沒有顯示新的值。而getCurrentSession在事務提交後會自動關閉當前session。

所以,一般推薦使用getCurrentSession,這樣需要我們關心的內容就更少,而且更不容易出錯。

當然,MyEclipse也不會放着高級的東西不用的,仔細查看上面的代碼,發現在openSession之前,session會先從threadLocal中獲取,這裏的threadLocal就可以類比爲getCurrentSession中配置的thread,所以,可以認爲MyEclipse是在openSession之前已經實現了從線程中獲取上下文的Session,所以直接使用MyEclipse生成的getSession的功能類似getCurrentSession,但是測試後發現,getSession在提交事務之後,並沒有自動關閉,仍然需要手動關閉。

爲什麼MyEclipse不使用getCurrentSession呢?查看生成的DAO類可以發現,MyEclipse生成的是沒有和事務相關的操作的,當然在進行save、update、delete操作時必須手動添加事務開始和事務提交,所以這裏在提交事務之後必須手動關閉session。而進行數據庫查找操作時,openSession是不需要提交事務的。

getCurrentSession則必須要打開一個新的事務,否則會報createQuery is not valid without active transaction錯誤。

從簡化操作的角度,直接使用MyEclipse的方法更爲簡單,但要記住增刪改操作必須手動添加事務,並在操作結束後關閉session。

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