細品hibernate的session

一、什麼是session

    簡單的來說,session類比於jdbc中的connection;

二、session的生命週期

     三大生命週期,參見:吾的hibernate總結;

三、細說session線程

session由sessionFactory創建

 

sessionFactory線程安全,

session線程不安全

 

解決session線程不安全問題

方案一

需要ThreadLocal;

ThreadLocal 是Java中一種較爲特殊的線程綁定機制,通過ThreadLocal存取的數據,總是與當前線程相關,也就是說,JVM 爲每個運行的線程,綁定了私有的本地實例存取空間,從而爲多線程環境常出現的併發訪問問題提供了一種隔離機制,ThreadLocal並不是線程本地化的實現,而是線程局部變量。

也就是說每個使用該變量的線程都必須爲該變量提供一個副本,每個線程改變該變量的值僅僅是改變該副本的值,而不會影響其他線程的該變量的值,ThreadLocal是隔離多個線程的數據共享,不存在多個線程之間共享資源,因此不再需要對線程同步。

 

例子

public class HibernateUtil {  
 
public static final SessionFactory sessionFactory;  
public static final ThreadLocal session = new ThreadLocal();  
//創建 Configuration容器,可以把其理解爲一容器,容器的生命週期就是在一個線程中 
static{  
 
try{  
 
Configuration configuration=new Configuration().configure(); 
sessionFactory = configuration.buildSessionFactory();  
 
}catch (Throwable ex){  
 
System.err.println("Initial SessionFactory creation failed." + ex);  
throw new ExceptionInInitializerError(ex);  
}  
}  
 
public static Session currentSession() throws HibernateException{  
Session s = (Session) session.get();  
if (s == null)  
{  
s = sessionFactory.openSession();  
session.set(s); //將session裝入 Configuration容器
}  
return s;  
}  
 
public static void closeSession() throws HibernateException {  
Session s = (Session) session.get();  
if (s != null)  
s.close();//清空容器
session.set(null);  
}  
} 


解決方案二

對象的生命週期與本地線程綁定(通過Thread-local傳播Session,線程本地化)

¨       如果把 Hibernate 配置文件的 hibernate.current_session_context_class 屬性值設爲 thread, Hibernate 就會按照與本地線程綁定的方式來管理 Session

¨       Hibernate 按以下規則把 Session 與本地線程綁定

          當一個線程(threadA)第一次調用 SessionFactory 對象的 getCurrentSession() 方法時, 該方法會創建一個新的 Session(sessionA) 對象, 把該對象與 threadA 綁定, 並將 sessionA 返回

          threadA 再次調用 SessionFactory 對象的 getCurrentSession() 方法時, 該方法將返回 sessionA 對象

          threadA 提交 sessionA 對象關聯的事務時, Hibernate 會自動清理 sessionA 對象的緩存, 然後提交事務, 關閉 sessionA 對象. threadA 撤銷 sessionA 對象關聯的事務時, 也會自動關閉 sessionA 對象

          threadA 再次調用 SessionFactory 對象的 getCurrentSession() 方法時, 該方法會又創建一個新的 Session(sessionB) 對象, 把該對象與 threadA 綁定, 並將 sessionB 返回

 

配置:

¨       hibernate.cfg.xml文件中增加

          <!-- 配置session的線程本地化 threadLocal -->

           <property name="current_session_context_class">thread</property>

¨       不是調用sessionFactory.openSession().而是調用sessionFactory. getCurrentSession().獲取session對象.從當前的線程提取session

          當前線程如果存在session對象,取出直接使用

          當前線程如果不存在session對象,獲取一個新的session對象和當前的線程綁定

 

 

 

 


 

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