细品hibernate的session

2014-11-24 03:31:45 · 作者: · 浏览: 0

一、什么是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文件中增加

thread

¨ 不是调用sessionFactory.openSession().而是调用sessionFactory. getCurrentSession().获取session对象.从当前的线程提取session:

当前线程如果存在session对象,取出直接使用

当前线程如果不存在session对象,获取一个新的session对象和当前的线程绑定