两种事务HibernateTransactionManager 和DataSourceTransactionManager
来源:互联网 发布:网络modbus报文 编辑:程序博客网 时间:2024/03/28 18:56
spring中常用的事务管理有DataSourceTransactionManager 和HibernateTransactionManager,他们服务的对象不同,下面来简单说明一下:
1、DataSourceTransactionManager:此事务管理器是针对传统的JDBC进行事务管理,在spring中是对JdbcTemplate进行事务管理
2、HibernateTransactionManager:是对hibernate进行事务管理,当在spring中使用HibernateTemplate时,要使用此管理器。
但是当在service的一个方法中同时使用了JdbcTemplate和HibernateTemplate时,就要使用HibernateTransactionManager了,因为当使用DataSourceTransactionManager时,JdbcTemplate和HibernateTemplate获得的connection并不是同一个,也就没办法对service的方法进行事务管理了。
如果一个方法中既用了HibernateTemplate,又用了JdbcTemplate,应该怎么配单实例的db事务呢(多例免谈)用 DataSouceTransactionManager是不行的,而用HibernateTransactionManager就可以保证
原因的话看下它们源代码,会发现HibernateTransactionManager中的处理可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接
原文如下=====================================================================
今天这边报出一个问题,他在一个service方法里面,用了jdbcdaosupport的dao又用了hibernateDaoSupport的dao,在spring里面给service方法配上了事务,
但是通过MySQL的bin log,发现这种不同的dao使用的连接id不是同一个,即jdbctemplate使用了一个链接,而hibernatetemplate使用了另外一个链接,这样虽然两种dao都是针对一个mysql实例,但却没法保证事务。
之前xd提过使用hibernateTransaction manager,可以保证混用时候的事务,但是却不知道为啥会这样。我们这边就以为datasourcetransactionmanager也是一样,但发现事实上不一样。确实我们换成hibernateTransaction manager,两种dao使用的connection就归一了,真好,但是为啥呢?
翻了半天spring的源代码终于找到了。
以下是datasourceTransactionManager的doGetTransaction和doBegin代码
- protected Object doGetTransaction() {
- //只是设定一个dataSource为key的存放connection的threadlcal
- DataSourceTransactionObject txObject = new DataSourceTransactionObject();
- txObject.setSavepointAllowed(isNestedTransactionAllowed());
- ConnectionHolder conHolder =
- (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
- txObject.setConnectionHolder(conHolder, false);
- return txObject;
- }
- protected void doBegin(Object transaction, TransactionDefinition definition) {
- .....
- try {
- if (txObject.getConnectionHolder() == null ||
- txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
- Connection newCon = this.dataSource.getConnection();
- }
- ....
- //从datasource拿一个连接,放入thread生命周期的holder
- }
这就完了。
然后jdbctemplate会通过datasourceutil去拿这个holder里面的connection
从而在一个事务里使用这个连接。
但是hibernateTransactionManager呢:
- 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, false);
- }
- if (getDataSource() != null) {
- ConnectionHolder conHolder = (ConnectionHolder)
- TransactionSynchronizationManager.getResource(getDataSource());
- txObject.setConnectionHolder(conHolder);
- }
- return txObject;
- }
- //两个holder都管!
- protected void doBegin(Object transaction, TransactionDefinition definition) {
- .....
- try {
- if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
- Interceptor entityInterceptor = getEntityInterceptor();
- Session newSession = (entityInterceptor != null ?
- getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
- if (logger.isDebugEnabled()) {
- logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
- "] for Hibernate transaction");
- }
- txObject.setSessionHolder(new SessionHolder(newSession), true);
- }
- .....
- //从sessionFactory拿个新session,也会产生一个新连接
- session = txObject.getSessionHolder().getSession();
- if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
- // We're allowed to change the transaction settings of the JDBC Connection.
- if (logger.isDebugEnabled()) {
- logger.debug(
- "Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
- }
- //原来直接把session后面的connection也放入holder
- Connection con = session.connection();
- Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
- txObject.setPreviousIsolationLevel(previousIsolationLevel);
- }
所以如果使用hibernateTransactionManager的话,就完全可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接!所有的疑问烟消云散了,
所以大家还是使用hibernateTransactionManager从而随心所欲的使用jdbctemplate和hibernatetemplate吧
原文来自:http://www.pinhuba.com/spring/101108.htm
http://bjyzxxds.iteye.com/blog/427309
- 两种事务HibernateTransactionManager 和DataSourceTransactionManager
- HibernateTransactionManager和DataSourceTransactionManager
- HibernateTransactionManager和DataSourceTransactionManager
- HibernateTransactionManager和DataSourceTransactionManager
- 关于spring中HibernateTransactionManager和DataSourceTransactionManager
- Spring 事务管理 DataSourceTransactionManager 和 DataSourceTransactionManager
- HibernateTransactionManager管理事务
- HibernateTransactionManager配单例事务
- HibernateTransactionManager 和 hibernateTemplate的区别
- HibernateTransactionManager 和 hibernateTemplate的区别
- HibernateTransactionManager 和 hibernateTemplate的区别
- 事务和两阶段提交
- 事务和两阶段提交
- 事务和两阶段提交
- 事务和两阶段提交
- Spring3.1.0实现原理分析(二十二).Dao事务分析之事务管理器DataSourceTransactionManager
- 数据库的两种CRUD和事务,listview
- ssh框架中事务的声明和两种配置事务的方法
- javascript个人小结
- Leetcode 19 Remove Nth Node From End of List
- 值传递与引用传递及延伸小知识
- tigase rest Api 发送消息 解决消息中文乱码问题
- 计算机视觉基础(二)——使用标定出的R和T进行摄像机坐标系定位
- 两种事务HibernateTransactionManager 和DataSourceTransactionManager
- 自定义下拉框样式 火狐 谷歌 IE
- 札记2
- K60学习笔记3——Linker
- 群晖系统挂载NTFS硬盘
- xml常用样式实现
- JNI常用函数说明一
- 批量删除js向后台传值正确,却删不了
- 代码适配Masonry使用的详细介绍