http://blog.csdn.net/mypop/article/details/6120377
在项目中同时用到了JDBC和Hibernate,分别配置了各自的事务,同时配置了不同的tx:annotation-driven。
但是在实际使用中,只有配置在前的tx:annotation-driven起了作用,另外一个tx:annotation-driven不起作用。
===============
http://zhangxiaoming.iteye.com/blog/307670
最近开发中,遇到了这样一个问题。
1.系统中,事务是有spring管理的。
2.系统中,即用到了JDBC,又用到了Hibernate。
3.spring管理了jdbc事务,也管理了Hibernate事务。
如上3点所述,存在这样的情况:
配置了jdbc事务的service,注入了配置了hibernate事务的service。这时,执行的时候,系统就会抛出异常:
org.springframework.transaction.IllegalTransactionStateException: Pre-bound JDBC connection found - HibernateTransactionManager does not support running within DataSourceTransactionManager if told to manage the DataSource itself. It is recommended to use a single HibernateTransactionManager for all transactions on a single DataSource, no matter whether Hibernate or JDBC access.
但是,由配置了hibernate事务的service,注入了配置了jdbc事务的service。就能正常运行。
不知道大家有没有遇到过类似的问题。一起讨论一下。
================
http://www.iteye.com/topic/37707
最近摸索了一下Hibernate与JDBC(iBATIS)事务整合问题,算是有点收获,写出来和大家讨论一下吧。。。
一般大家都会使用Spring声明型事务 transactionAttributes 为 PROPAGATION_REQUIRED
Hibernate 使用 HibernateTransactionManager 、JDBC(iBATIS) 使用 DataSourceTransactionManager
当需要将它们整合到一个事务中的时候
普通的做法是配置统一的DataSource, Hibernate与JDBC(iBATIS) 都使用HibernateTransactionManager
坛子里有篇帖子已经详细论述了这种整合方案 http://www.iteye.com/topic/11063?page=2
------------------------------------------------------
Hibernate与JDBC(iBATIS) 都使用DataSourceTransactionManager又可不可以呢?
普遍的看法是 NO! 认为DataSourceTransactionManager根本就不处理Hibernate的session,事务当然无法实现。。。
但事实是否真的如此呢?
答案同样是 NO! http://forum.springframework.org/archive/index.php/t-9878.html
Juergen Hoeller:
Just if you proxy your JDBC DataSource with a TransactionAwareDataSourceProxy (available since Spring 1.1 RC1) and pass that proxy to your LocalSessionFactoryBean, you could use DataSourceTransactionManager in combination with Hibernate.
也就是说配置 sessionFactory 的 useTransactionAwareDataSource 为 true
Hibernate与JDBC(iBATIS) 都使用 DataSourceTransactionManager 同样可以保证事务
原理就是保证了 connection 的唯一性。
====================http://www.iteye.com/topic/11063?page=2
楼主以及二楼的朋友的论断错误倒也罢了,那种肯定的,结论性总结的态度很容易误导初学者的学习和理解。
提个小小的建议:下结论前要进行充分的考证,我们技术工作者尤其需要严谨的态度。需要用证据来说话。
jdo dao和jdbc dao能否在同一个事务里这我不太清楚。因为我没用过jdo daosupport。
但是jdbc daosupport和hibernate daosupport却能被wrap到同一个事务里。成立需要几点条件:
1、使用同一个datasource
2、事务交由hibernateTransactionManager管理
3、相关dao以及service需要使用runtime exception体系,使用spring提供的exception可以,自己封装设计的runtime exception体系也行。
与此相关的事务代码片断在HibernateTransactionManager类中。最好可以把DatasourceTransactionManager和HibernateTransactionManager对比来看。
在此贴上几个源码片断,多余的我就不解释了。相信大家一看自明。
HibernateTransactionManager#doGetTransaction
- HibernateTransactionObject txObject = new HibernateTransactionObject();;
- txObject.setSavepointAllowed(isNestedTransactionAllowed(););;
- if (TransactionSynchronizationManager.hasResource(getSessionFactory(););); {
- SessionHolder sessionHolder =
- (SessionHolder); TransactionSynchronizationManager.getResource(getSessionFactory(););;
- if (logger.isDebugEnabled();); {
- logger.debug("Found thread-bound session [" + sessionHolder.getSession(); +
- "] for Hibernate transaction");;
- }
- txObject.setSessionHolder(sessionHolder, false);;
- if (getDataSource(); != null); {
- ConnectionHolder conHolder = (ConnectionHolder);
- TransactionSynchronizationManager.getResource(getDataSource(););;
- txObject.setConnectionHolder(conHolder);;
- }
- }
- return txObject;
- HibernateTransactionObject txObject = new HibernateTransactionObject();;
- txObject.setSavepointAllowed(isNestedTransactionAllowed(););;
- if (TransactionSynchronizationManager.hasResource(getSessionFactory(););); {
- SessionHolder sessionHolder =
- (SessionHolder); TransactionSynchronizationManager.getResource(getSessionFactory(););;
- if (logger.isDebugEnabled();); {
- logger.debug("Found thread-bound session [" + sessionHolder.getSession(); +
- "] for Hibernate transaction");;
- }
- txObject.setSessionHolder(sessionHolder, false);;
- if (getDataSource(); != null); {
- ConnectionHolder conHolder = (ConnectionHolder);
- TransactionSynchronizationManager.getResource(getDataSource(););;
- txObject.setConnectionHolder(conHolder);;
- }
- }
- return txObject;
HibernateTransactionObject txObject = new HibernateTransactionObject();;
txObject.setSavepointAllowed(isNestedTransactionAllowed(););;
if (TransactionSynchronizationManager.hasResource(getSessionFactory(););); {
SessionHolder sessionHolder =
(SessionHolder); TransactionSynchronizationManager.getResource(getSessionFactory(););;
if (logger.isDebugEnabled();); {
logger.debug("Found thread-bound session [" + sessionHolder.getSession(); +
"] for Hibernate transaction");;
}
txObject.setSessionHolder(sessionHolder, false);;
if (getDataSource(); != null); {
ConnectionHolder conHolder = (ConnectionHolder);
TransactionSynchronizationManager.getResource(getDataSource(););;
txObject.setConnectionHolder(conHolder);;
}
}
return txObject;
由此可以看出hibernateTransactionManager可以检测到绑定在当前线程上的connection
HibernateTransactionManager#doBegin
- Connection con = session.connection();;
- Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);;
- txObject.setPreviousIsolationLevel(previousIsolationLevel);;
- ...........
- if (getDataSource(); != null); {
- ConnectionHolder conHolder = new ConnectionHolder(con);;
- if (definition.getTimeout(); != TransactionDefinition.TIMEOUT_DEFAULT); {
- conHolder.setTimeoutInSeconds(definition.getTimeout(););;
- }
- if (logger.isDebugEnabled();); {
- logger.debug("Exposing Hibernate transaction as JDBC transaction [" +
- conHolder.getConnection(); + "]");;
- }
- TransactionSynchronizationManager.bindResource(getDataSource();, conHolder);;
- txObject.setConnectionHolder(conHolder);;
- }
- // bind the session holder to the thread
- if (txObject.isNewSessionHolder();); {
- TransactionSynchronizationManager.bindResource(getSessionFactory();, txObject.getSessionHolder(););;
- }
- Connection con = session.connection();;
- Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);;
- txObject.setPreviousIsolationLevel(previousIsolationLevel);;
- ...........
- if (getDataSource(); != null); {
- ConnectionHolder conHolder = new ConnectionHolder(con);;
- if (definition.getTimeout(); != TransactionDefinition.TIMEOUT_DEFAULT); {
- conHolder.setTimeoutInSeconds(definition.getTimeout(););;
- }
- if (logger.isDebugEnabled();); {
- logger.debug("Exposing Hibernate transaction as JDBC transaction [" +
- conHolder.getConnection(); + "]");;
- }
- TransactionSynchronizationManager.bindResource(getDataSource();, conHolder);;
- txObject.setConnectionHolder(conHolder);;
- }
- // bind the session holder to the thread
- if (txObject.isNewSessionHolder();); {
- TransactionSynchronizationManager.bindResource(getSessionFactory();, txObject.getSessionHolder(););;
- }
Connection con = session.connection();;
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);;
txObject.setPreviousIsolationLevel(previousIsolationLevel);;
..............
if (getDataSource(); != null); {
ConnectionHolder conHolder = new ConnectionHolder(con);;
if (definition.getTimeout(); != TransactionDefinition.TIMEOUT_DEFAULT); {
conHolder.setTimeoutInSeconds(definition.getTimeout(););;
}
if (logger.isDebugEnabled();); {
logger.debug("Exposing Hibernate transaction as JDBC transaction [" +
conHolder.getConnection(); + "]");;
}
TransactionSynchronizationManager.bindResource(getDataSource();, conHolder);;
txObject.setConnectionHolder(conHolder);;
}
// bind the session holder to the thread
if (txObject.isNewSessionHolder();); {
TransactionSynchronizationManager.bindResource(getSessionFactory();, txObject.getSessionHolder(););;
}
由此可以看出,在真正启动一个事务时,hbTxnManager会先把connection绑定到当前线程,再绑定session到当前线程,由TransactionSynchronizationManager统一管理。并且上面提到的connection是从session中取得的,也就是说,无论是jdbc dao还是hibernate dao本质上使用的是同一个database connection
因此得出结论:HibernateTransactionManager实际上是可以同时管理由JdbcTemplate或JdbcDaoSupport实现的dao以及HibernateTemplate或HibernateDaoSupport实现的事务的。
Rod Johnson的话:
The only issue to watch, of course, is that you may be invalidating your Hibernate cache by JDBC changes. Generally I find it best to use JDBC to update only tables that don't have Hibernate mappings.
Juergen Hoeller的话:
Note that you must specify the DataSource for Hibernate via LocalSessionFactoryBean's "dataSource" property to allow HibernateTransactionManager to auto-detect it. Alternatively, you can explicitly pass the DataSource to HibernateTransactionManager's "dataSource" property.