Spring事务管理之HibernateTransactionManager
来源:互联网 发布:mysql offset用法 编辑:程序博客网 时间:2024/03/29 06:51
对于Spring的事务管理,我们一般只知道是采用AOP(面向切面)的方式进行事务管理。也就是说,在执行Service方法时,Spring会通过动态代理的方式去获取执行service方法的对象,然后在执行具体的业务方法之前和之后,可以加入spring的事务管理。
问题来了,既然要进行事务管理,spring必须要拿到service方法中使用的connection对象,在Hibernate中也就是session对象。本章节就为大家揭开Spring是如何获取到同一个connection对象的。这里我们拿HibernateTransactionManager来举例。
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /></bean>
在service中的如何获取session对象,一般是用SessionFactory.getCurrentSession()。我们来看一下SessionFactory中的getCurrentSession()具体实现方法
private final transient CurrentSessionContext currentSessionContext;public org.hibernate.classic.Session getCurrentSession() throws HibernateException { if ( currentSessionContext == null ) { throw new HibernateException( "No CurrentSessionContext configured!" ); } return currentSessionContext.currentSession(); }
可以看出返回的是从CurrentSessionContext中获取当前的session,再看其中一种实现方式ThreadLocalSessionContext。
private static final ThreadLocal context = new ThreadLocal(); public final Session currentSession() throws HibernateException { Session current = existingSession( factory ); if (current == null) { current = buildOrObtainSession(); // register a cleanup synch current.getTransaction().registerSynchronization( buildCleanupSynch() ); // wrap the session in the transaction-protection proxy if ( needsWrapping( current ) ) { current = wrap( current ); } // then bind it doBind( current, factory ); } return current; } private static Session existingSession(SessionFactory factory) { Map sessionMap = sessionMap(); if ( sessionMap == null ) { return null; } else { return ( Session ) sessionMap.get( factory ); } } protected static Map sessionMap() { return ( Map ) context.get(); }
上面的代码中有一个静态成员变量context,从这几个方法中大致可以看出,session实际上是从一个名为context的ThreadLocal静态变量中获取当前的线程中的session。假如是session不存在,则将产生一个新的Session然后在绑定到ThreadLocal中。
以上是调用SessionFactory.getCurrentSession()是怎么返回session的代码解读。然后再来读一下Spring的HibernateTransactionManager的代码。
找到doGetTransaction()方法,这个方法是获取事务管理器。其中可以看到假如sessionHolder为空,则获取session对象也是调用SessionFactory中的getCurrentSession()方法。
@Override protected Object doGetTransaction() { HibernateTransactionObject txObject = new HibernateTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory()); if (sessionHolder != null) { if (logger.isDebugEnabled()) { logger.debug("Found thread-bound Session [" + SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction"); } txObject.setSessionHolder(sessionHolder); } else if (this.hibernateManagedSession) { try { //获取session Session session = getSessionFactory().getCurrentSession(); if (logger.isDebugEnabled()) { logger.debug("Found Hibernate-managed Session [" + SessionFactoryUtils.toString(session) + "] for Spring-managed transaction"); } txObject.setExistingSession(session); } catch (HibernateException ex) { throw new DataAccessResourceFailureException( "Could not obtain Hibernate-managed Session for Spring-managed transaction", ex); } } if (getDataSource() != null) { ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(getDataSource()); txObject.setConnectionHolder(conHolder); } return txObject; }
结论:在一个线程中,不论何时获取当前的Session都会是同于一个对象。
(注:ThreadLocal这里解释一下,是为每个线程都拷贝一份独立的对象,每个线程之间互不干扰。)
用一个流程图来表示一下:
- Spring事务管理之HibernateTransactionManager
- HibernateTransactionManager事务管理
- HibernateTransactionManager事务管理
- HibernateTransactionManager 事务管理实现
- 事务管理之Spring事务管理
- spring事物控制--HibernateTransactionManager
- Spring总结之事务管理
- Spring总结之事务管理
- spring之事务管理
- Spring之事务管理详解
- Spring之五 事务管理
- Spring注解之事务管理
- spring之事务管理1
- spring之事务管理2
- spring之事务管理
- Spring之事务管理
- 【Spring学习】之 事务管理
- Spring之事务管理
- 多进程通信
- 《tar命令打包格式及组合find应用原理及误区详解》
- UE3 Animation Compression Technical Guide
- MySql
- 解决android4.4以上系统的相册选择图片后获取不到有效的URI
- Spring事务管理之HibernateTransactionManager
- 双核心四线程变成单核心单线程,肿么办
- ffmpeg的php扩展 在64位系统下的安装
- Linux tcpdump命令详解
- google可用host3月2日
- Iptables之FORWARD转发链
- 内存优化学习
- 74.Which statements are true regarding single row functions? (Choose all that apply.)
- scala对时间(date)字符串转化为时间戳timestamp的实现