首先OpenSession()是永遠打開一個新的session,這個可以通過下面的方法來證明:
@Test
public void test() {
Student s = new Student();
StudentPK pk = new StudentPK();
s.setPk(pk);
s.setAge(23);
s.setClasses(1);
pk.setId(1);
pk.setName("moluo");
Session session = sf.openSession();
Session session1 = sf.openSession();
session.beginTransaction();
session.save(s);
System.out.println(session == session1); //輸出結果爲false;
session.getTransaction().commit();
session.close();
session1.close();
}
輸出結果爲false,顯然這倆session不是同一個session,所以openSession()每次都是new一個新的session。
其次,OpenSession()打開一個session以後必須顯式的去關閉(session.close())。
再來看看getCurrentSession(),它是從上下文裏找,如果有session,它就使用原來的session,如果沒有它就new一個session。怎麼證明呢?來看看下面這個例子:
@Test
public void test() {
Student s = new Student();
StudentPK pk = new StudentPK();
s.setPk(pk);
s.setAge(23);
s.setClasses(1);
pk.setId(1);
pk.setName("moluo");
Session session = sf.getCurrentSession();
Session session1 = sf.getCurrentSession();
session.beginTransaction();
session.save(s);
System.out.println(session == session1); //輸出結果爲true;
session.getTransaction().commit();
//session.close();
//session1.close();
}
輸出結果爲true,顯然這倆session是同一個session,否則輸出結果就是false了,也就是說當上下文如果存在一個session,它就使用原來的session。在事物沒有提交或者回滾之前,無論我們拿多少次session,它們都是同一個session,但如果提交或者回滾了,再拿就是新的session了。
另外,getCurrentSession()不需要我們顯式的去關閉,因爲當事物提交(session.getTransaction().commit())或者回滾之後,會自動的幫我們去關閉session。如果我們顯式的去關閉session,就有可能會出現問題,所以不要去多此一舉。
既然提到了他倆都可以獲取session,那麼他倆獲取到的session是否爲同一個session呢?再看下面的例子:
@Test
public void test() {
Student s = new Student();
StudentPK pk = new StudentPK();
s.setPk(pk);
s.setAge(23);
s.setClasses(1);
pk.setId(1);
pk.setName("moluo");
Session session = sf.openSession();
Session session1 = sf.getCurrentSession();
session.beginTransaction();
session.save(s);
System.out.println(session == session1); //輸出結果爲false;
session.getTransaction().commit();
//session.close();
}
輸出結果爲false,證明他倆不是同一個session,有些朋友就有可能會有疑問了,session1是通過getCurrentSession()得到的,而getCurrentSession()不是通過上下文獲取session嗎?上下文不是openSession(),不是已經有了一個session了嗎?實際上session是一個接口,通過這倆方式得到的session的具體實現方式是不一樣的,所以輸出結果爲false。
講到getCurrentSession()會從上下文裏獲取session,那麼上下文的配置在哪呢?實際上在sf = new AnnotationConfiguration().configure().buildSessionFactory();這步就已經調用配置文件hibernate.cfg.xml了,如果配置文件不是這個默認名,而是hibernate.xml,那麼就必須改成:
sf = new AnnotationConfiguration().configure(“hibernate.xml”).buildSessionFactory();也就是說在configure()方法就調用了配置文件。
迴歸正題:上下文配置在配置文件的:
<property name="current_session_context_class">thread</property>
這裏一共有4個可選的參數,分別是:jta,thread,custom,managed。前兩者比較常用,後兩者很少用到。
thread使用connection,用於單數據庫連接事物管理,而jta(java transaction api)運行時需要application server提供支持,它主要用於多數據庫,分佈式事物管理,用於界定事物邊界。
另外,getCurrentSession()創建的session會綁定到當前線程中,而openSession()不會綁定。
最後還有一點就是:openSession()可以在不開啓事物的情況下執行,而getCurrentSession()不行。(這個是在網上看來的,未經佐證!)
尊重版權,轉載請不要刪除下方二維碼並註明本文鏈接
歡迎關注行者摩羅微信公衆號(xingzhemoluo),共同交流編程經驗,掃描下方二維碼即可;