?.0.1版本开始,Hibernate增加了SessionFactory.getCurrentSession()Ҏ?/span>一开始,它假定了采用JTA事务QJTA事务定义了当前session的范围和上下?scope and context)。Hibernate开发团队坚信,因ؓ有好几个独立的JTA TransactionManager实现E_可用Q不论是否被部vC个J2EE容器中,大多?假若不是所有的Q应用程序都应该采用JTA事务理。基于这一点,采用JTA的上下文相关session可以满你一切需要?/p>
更好的是Q从3.1开始,SessionFactory.getCurrentSession()的后台实现是可拔插的。因此,我们引入了新的扩展接?(org.hibernate.context.CurrentSessionContext)和新的配|参?(hibernate.current_session_context_class)Q以便对什么是“当前session”的范围和上下?scope and context)的定义进行拔插?/p>
请参?org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有关于它的契U的详细讨论。它定义了单一的方法,currentSession()Q特定的实现用它来负责跟t当前的上下文session。Hibernate内置了此接口的两U实现?/p>
org.hibernate.context.JTASessionContext - 当前sessionҎJTA来跟t和界定。这和以前的仅支持JTA的方法是完全一L。详情请参阅Javadoc?/p>
org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线E来跟踪和界定。详情也请参阅Javadoc?/p>
q两U实现都提供?#8220;每数据库事务对应一个session”的编E模型,也称作每ơ请求一个session。Hibernate session的v始和l结由数据库事务的生存来控制。假若你采用自行~写代码来管理事务(比如Q在Ua的J2SE,或?JTA/UserTransaction/BMTQ,你用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行,事务边界是声明式定义的,你不需要在代码中进行Q何事务或 session理操作。请参阅W?11 ?事务和ƈ发一节来阅读更多的内容和CZ代码?/p>
hibernate.current_session_context_class 配置参数定义了应该采用哪个org.hibernate.context.CurrentSessionContext实现。注意,Z向下兼容Q如果未配置此参敎ͼ但是存在org.hibernate.transaction.TransactionManagerLookup的配|,Hibernate会采用org.hibernate.context.JTASessionContext。一般而言Q此参数的值指明了要用的实现cȝ全名Q但那两个内|的实现可以使用写,?jta"?thread"?/p>
1、getCurrentSession()与openSession()的区别?
* 采用getCurrentSession()创徏的session会绑定到当前U程中,而采用openSession()
创徏的session则不?br />
* 采用getCurrentSession()创徏的session在commit或rollback时会自动关闭Q而采用openSession()
创徏的session必须手动关闭
2、用getCurrentSession()需要在hibernate.cfg.xml文g中加入如下配|:
* 如果使用的是本地事务Qjdbc事务Q?br />
<property name="hibernate.current_session_context_class">thread</property>
* 如果使用的是全局事务Qjta事务Q?br />
<property name="hibernate.current_session_context_class">jta</property>
利于ThreadLocal模式理Session
早在Java1.2推出之时QJavaq_中就引入了一个新的支持:java.lang.ThreadLocalQ给我们在编写多U程E序
时提供了一U新的选择。ThreadLocal是什么呢Q其实ThreadLocalq是一个线E的本地实现版本Q它q不是一个ThreadQ?br />
而是thread local variable(U程局部变?。也许把它命名ؓThreadLocalVar更加合适。线E局部变?ThreadLocal)
其实的功用非常简单,是为每一个用某变量的线E都提供一个该变量值的副本Q是每一个线E都可以独立地改变自q副本Q?br />
而不会和其它U程的副本冲H。从U程的角度看Q就好像每一个线E都完全拥有一个该变量?br />
ThreadLocal是如何做Cؓ每一个线E维护变量的副本的呢Q其实实现的思\很简单,在ThreadLocalcM有一个MapQ?br />
用于存储每一个线E的变量的副本。比如下面的CZ实现(Z单,没有考虑集合的泛?Q?br />
public class HibernateUtil {
public static final ThreadLocal session =new ThreadLocal();
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session currentSession() throws HibernateException {
Session s = session.get();
if(s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = session.get();
if(s != null) {
s.close();
}
session.set(null);
}
}