HibernateTransactionManager事务管理

如果一个方法中既用了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代码

Java代码  

  1. protected Object doGetTransaction() {
  2. //只是设定一个dataSource为key的存放connection的threadlcal
  3. DataSourceTransactionObject txObject = new DataSourceTransactionObject();
  4. txObject.setSavepointAllowed(isNestedTransactionAllowed());
  5. ConnectionHolder conHolder =
  6. (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
  7. txObject.setConnectionHolder(conHolder, false);
  8. return txObject;
  9. }
  10. protected void doBegin(Object transaction, TransactionDefinition definition) {
  11. .....
  12. try {
  13. if (txObject.getConnectionHolder() == null ||
  14. txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
  15. Connection newCon = this.dataSource.getConnection();
  16. }
  17. ....
  18. //从datasource拿一个连接,放入thread生命周期的holder
  19. }

这就完了。

然后jdbctemplate会通过datasourceutil去拿这个holder里面的connection

从而在一个事务里使用这个连接。

但是hibernateTransactionManager呢:

Java代码  

  1. protected Object doGetTransaction() {
  2. HibernateTransactionObject txObject = new HibernateTransactionObject();
  3. txObject.setSavepointAllowed(isNestedTransactionAllowed());
  4. SessionHolder sessionHolder =
  5. (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
  6. if (sessionHolder != null) {
  7. if (logger.isDebugEnabled()) {
  8. logger.debug("Found thread-bound Session [" +
  9. SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
  10. }
  11. txObject.setSessionHolder(sessionHolder, false);
  12. }
  13. if (getDataSource() != null) {
  14. ConnectionHolder conHolder = (ConnectionHolder)
  15. TransactionSynchronizationManager.getResource(getDataSource());
  16. txObject.setConnectionHolder(conHolder);
  17. }
  18. return txObject;
  19. }
  20. //两个holder都管!
  21. protected void doBegin(Object transaction, TransactionDefinition definition) {
  22. .....
  23. try {
  24. if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
  25. Interceptor entityInterceptor = getEntityInterceptor();
  26. Session newSession = (entityInterceptor != null ?
  27. getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
  28. if (logger.isDebugEnabled()) {
  29. logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
  30. "] for Hibernate transaction");
  31. }
  32. txObject.setSessionHolder(new SessionHolder(newSession), true);
  33. }
  34. .....
  35. //从sessionFactory拿个新session,也会产生一个新连接
  36. session = txObject.getSessionHolder().getSession();
  37. if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
  38. // We‘re allowed to change the transaction settings of the JDBC Connection.
  39. if (logger.isDebugEnabled()) {
  40. logger.debug(
  41. "Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
  42. }
  43. //原来直接把session后面的connection也放入holder
  44. Connection con = session.connection();
  45. Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
  46. txObject.setPreviousIsolationLevel(previousIsolationLevel);
  47. }

所以如果使用hibernateTransactionManager的话,就完全可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接!所有的疑问烟消云散了, 
所以大家还是使用hibernateTransactionManager从而随心所欲的使用jdbctemplate和hibernatetemplate吧

时间: 2024-10-13 23:01:40

HibernateTransactionManager事务管理的相关文章

[转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊

原文地址:http://stamen.iteye.com/blog/1441758 有些人很少使用Spring而不使用Spring事务管理器的应用,因此常常有人会问:是否用了Spring,就一定要用Spring事务管理器,否则就无法进行数据的持久化操作呢?事务管理器和DAO是什么关系呢?   也许是DAO和事务管理如影随行的缘故吧,这个看似简单的问题实实在在地存在着,从初学者心中涌出,萦绕在老手的脑际.答案当然是否定的!我们都知道:事 务管理是保证数据操作的事务性(即原子性.一致性.隔离性.持久

Spring 事务管理高级应用难点剖析--转

第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN&en=utf&hpp=20&dws=cndw&lo=zh 概述 Spring 最成功,最吸引人的地方莫过于轻量级的声明式事务管理,仅此一点,它就宣告了重量级 EJB 容器的覆灭.Spring 声明式事务管理将开发者从繁复的事务管理代码中解脱出来,专注于业务逻辑的开发上,这是一件

spring mvc+hibernate 实现事务管理(全注解版)

为了方便项目变大配置文件变多,用注解代替 *.hbm.xml,<bean id="*dao" class="">,另外用反省实现dao操作,省去每个类一个dao,此处参考了鸵鸟的例子. 实现功能跟http://blog.csdn.net/waiwai4701/article/details/38270721这个项目是一样的,controller和页面就不再写 首先,jar包支持,为了方便jar包管理采用maven技术,服务器没有用tomcat用的jett

Spring 事务管理高级应用难点剖析: 第 1 部分

Spring 的事务管理是被使用得最多的功能之一,虽然 Spring 事务管理已经帮助程序员将要做的事情减到了最小.但在实际开发中,如果使用不当,依然会造成数据连接泄漏等问题.本系列以实际应用中所碰到的各种复杂的场 景为着眼点,对这些应用的难点进行深度的剖析. DAO 和事务管理的牵绊 很少有使用 Spring 但不使用 Spring 事务管理器的应用,因此常常有人会问:是否用了 Spring,就一定要用 Spring 事务管理器,否则就无法进行数据的持久化操作呢?事务管理器和 DAO 是什么关

spring学习笔记:spring事务管理 (转)

关于事物隔离级别, 脏读, 不可重复读, 幻读的理解, 另有一篇文章比较生动的介绍:http://blog.csdn.net/sunxing007/article/details/6427290 spring事务管理相关的接口: TransactionDefinition:代表一个事物,描述了事务的隔离级别, 超时时间,事务是否只读, 传播规则等等; TransactionStatus:描述事物的状态; PlatformTransactionManager:事务管理器接口, 只定义了3个方法:g

Spring事务管理(详解+实例)

写这篇博客之前我首先读了<Spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

Spring整合hibernate4:事务管理

Spring和Hibernate整合后,通过Hibernate API进行数据库操作时发现每次都要opensession,close,beginTransaction,commit,这些都是重复的工作,我们可以把事务管理部分交给spring框架完成. 配置事务(xml方式) 使用spring管理事务后在dao中不再需要调用beginTransaction和commit,也不需要调用session.close(),使用API  sessionFactory.getCurrentSession()来

Spring事务管理

写这篇博客之前我首先读了<spring in action>,之后在网上看了一些关于Spring事务管理的文章,感觉都没有讲全,这里就将书上的和网上关于事务的知识总结一下,参考的文章如下: Spring事务机制详解 Spring事务配置的五种方式 Spring中的事务管理实例详解 1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是要么都执行要么都

24Spring_事务管理机制

第一部分:Spring事务管理高层抽象接口 我们介绍三个接口:1.PlatformTransactionManager 2.TransactionDefinition  3.TransactionStatus PlatformTransactionManager 平台事务管理器 使用Spring管理事务,需要为不同持久层技术实现,提供不同事务管理器(实现类).下面给一个PlatformTransactionManager的实现类的表. 这个表格的左侧的事务都是PlatformTransactio