spring
@transactional声明式事务管理
getcurrentsession
在spring
@transactional声明式事务管理的配置中,hibernate.current_session_context_class=thread…
这一句是不能加的…加了就会出错..那为什么不能加呢?
那是因为在spring事务管理中,current
session是绑定到springsessioncontext中的,而不是threadlocalsessioncontext中的
先结合bernate4.0说说:
从开
始,sessionfactory.getcurrentsession()的后台实现是可拔插的。因此,我们引入了新的扩展接口
(org.hibernate.context.spi.currentsessioncontext)和
新的配置参数(hibernate.current_session_context_class),以便对什么是“当前session”的范围和上下文(scope
and context)的定义进行拔插。
它定义
了单一的方法,currentsession(),特定的实现用它来负责跟踪当前的上下文session。
这个接口仅有一个方法:
currentsession()
throws
retrieve thecurrent session according to the scoping
defined by this implementation.
currentsession()表示
根据当前currentsessioncontext的实现及定义返回”当前的session”
这个接口…hibernate中有3个类实现了这个接口
all known implementing classes:
, ,
1:
org.hibernate.context.internal.threadlocalsessioncontext -
当前session通过当前执行的线程来跟踪和界定。
2:
org.hibernate.context.internal.jtasessioncontext-
当前session根据jta来跟踪和界定。这和以前的仅支持jta的方法是完全一样的。
3:
org.hibernate.context.internal.managedsessioncontext..
spring为事务管理,也实现了此接口:
1: org.springframework.orm.hibernate4.springsessioncontext–
当前session根据spring和事务管理器来跟踪和界定.
这几种实现都提供了“每数据库事务对应一个session”的编程模型,也称作每次请求一个session。hibernate session的起始和终结由数据库事务的生存来控制。
hibernate.current_session_context_class
配置参数定义了应该采用哪个org.hibernate.context.spi.currentsessioncontext实现。
一般而言,此参数的值指明了要使用的实 现类的全名,但那两个内置的实现可以使用简写,即"jta"和"thread"。
hibernate.current_session_context_class=thread
实质是:
hibernate.current_session_context_class= org.hibernate.context.internal.threadlocalsessioncontext
同理:
hibernate.current_session_context_class=jta
hibernate.current_session_context_class= org.hibernate.context.internal.jtasessioncontext
而在spring
@transactional声明式事务管理,”currentsession”的定义为: 当前被 spring事务管理器
管理的session,此时应配置:
hibernate.current_session_context_class=org.springframework.orm.hibernate4.springsessioncontext
spring 整合hibernate管理事务后,由spring的transactionmanager管理事务后,
currentsession是绑定到springsessioncontext的,而不是thread。
此时hibernate.current_session_context_class应该是springsessioncontext,而它又会在使用localsessionfactorybean时自动的设置。
所以就不需要你去设置current_session_context_class
- -
- -- -
下面我们来分析一下sessionfactoryimpl, org.hibernate.context.spi.currentsessioncontext
org.hibernate.context.internal.threadlocalsessioncontext
org.springframework.orm.hibernate4.springsessioncontext
这些类的源代码
分析sessionfactory.getcurrentsession() 我们跟进去
来到sessionfactoryimpl.getcurrentsession()方法:
sessionfactoryimpl
的currentsessioncontext属性的实际类型就是
由hibernate.current_session_context_class决定的…
2:首先设置: hibernate.current_session_context_class= org.hibernate.context.internal.threadlocalsessioncontext
到这一句,currentsessioncontext.currentsession()跟进去
现在对于hibernate.current_session_context_class= thread时的getcurrentsession()就很清楚了:
1:尝试取出绑定到线程的session
2:如果没有,则开启一个”事务提交后自动关闭”的session,并将此session加入到threadlocal的map中.
3:返回session
3:然后再分析:hibernate.current_session_context_class=org.springframework.orm.hibernate4.springsessioncontext
因为加入了@transactional,执行adduser()方法时,spring的transactionmanager会自动open
sesion,自动开启事务,并且将此sesion绑定到springsessioncontext(实际上是transactionsynchronizationmanager的threadlocal的map)中..
然后到sessionfactoryimpl.getcurrentsesssion()的currentsessioncontext.currentsession()这一句,跟进去
object value
=transactionsynchronizationmanager.getresource(this.sessionfactory);
关键是这一句,跟进去:
现在对于hibernate.current_session_context_class= org.springframework.orm.hibernate4.springsessioncontext时的getcurrentsession()就很清楚了:
@transactional声明的方法执行时,spring的transactionmanager会自动open
2:sessionfactory.getcurrentsession()方法执行时,调用springsessioncontext.currentsession()从transactionsynchronizationmanager的上下文中查找
当前的session
3:找到后返回当前的session,找不到,则返回hibernateexception("no
sessionfound for current thread")
ps:
从中,我们也知道了,执行sessionfactoryimpl.opensession()时,只是简单地new
一个sessionbuilder,然后调用sessionbuilder.opensession(),得到的session是不会绑定到任何
org.hibernate.context.spi.currentsessioncontext
在上下文中的.
////////////////////////////////////////////////////////////////---------------------------------------------------------------------------------------------------------------------------------------
总结: hibernate.current_session_context_class=thread(org.hibernate.context.internal.threadlocalsessioncontext)
与
hibernate.current_session_context_class=org.springframework.orm.hibernate4.springsessioncontext
时的sessionfactory.getcurrentsession()的不同之处在于:
前者在threadlocalsessioncontext里的线程局部的map中查找session,
而后者在springsessioncontext的上下文(transactionsynchronizationmanager里的线程局部的map)中查找...
最终,你会发觉,无论是threadlocalsessioncontext 或 springsessioncontext
查找的"currentsession",都是以类似键值对<sessionfactory,session>的形式存放到threadlocal的map中,也就是说这两者的上下文都是一个threadlocal的map...查找时以sessionfactory为键来查找对应的session,所以在同一线程中,一个sessionfactory只能有一个currentsession
转自: