hibernate之openSession()和getCurrentSession()的區別

        這幾天在學習hibernate的核心開發接口,瞭解到hibernate的session有兩種獲取方式,一種是通過Session session = sessionFactory.openSession()來獲取,另外一種是通過Session session = sessionFactory.getCurrentSession()方法來獲取,那麼這兩種方法有啥區別呢?

         首先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),共同交流編程經驗,掃描下方二維碼即可;

                                                        

         

發佈了41 篇原創文章 · 獲贊 14 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章