`

hibernate事务和jdbc事务冲突问题

阅读更多
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.


原帖:http://blog.csdn.net/zhangliao613/article/details/8277343

在项目中同时用到了JDBC和Hibernate,分别配置了各自的事务,同时配置了不同的tx:annotation-driven。

但是在实际使用中,只有配置在前的tx:annotation-driven起了作用,另外一个tx:annotation-driven不起作用。

===============

http://zhangxiaoming.iteye.com/blog/307670

spring 中 Hibernate 事务和JDBC事务嵌套问题
JDBCHibernateSpring配置管理ORM

最近开发中,遇到了这样一个问题。

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
Java代码 复制代码 收藏代码
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;
[java] view plaincopy
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;
[java] view plaincopy
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
Java代码 复制代码 收藏代码
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(););; 
}
[java] view plaincopy
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(););;
}
[java] view plaincopy
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的话:
引用
It is possible--and sometimes useful--to have coordinated transactions for both. Your JDBC transactions will be managed by the HibernateTransactionManager if you work with the same JDBC DataSource in the same transaction. That is, create the SessionFactory using Spring's SessionFactoryBean using the same DataSource that your JdbcTemplates use.

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的话:
引用
As Rod said, simply keep using HibernateTransactionManager, which auto-detects the DataSource used by Hibernate and seamlessly exposes Hibernate transactions as JDBC transactions for that DataSource. JDBC code that accesses the same DataSource via Spring will automatically participate in such transactions.

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.
分享到:
评论

相关推荐

    Hibernate事务和并发控制

    配置JDBC事务的方式是在`hibernate.cfg.xml`中设置`transaction.factory_class`属性为`org.hibernate.transaction.JDBCTransactionFactory`。使用JDBC事务的代码示例如下: ```java Transaction tx = null; try { ...

    hibernate事务,并发及缓存管理实例

    此外,Hibernate支持JTA(Java Transaction API)和JDBC事务管理,前者适用于多数据源环境,后者则适用于单数据源。 二、并发控制 在多用户环境下,并发问题如脏读、不可重复读和幻读是常见的问题。Hibernate通过...

    Hibernate4实战 之第五部分:Hibernate的事务和并发

    #### 二、Hibernate事务管理机制 Hibernate 本身不实现事务逻辑,而是依赖于底层的数据源(JDBC 或 JTA)来实现事务管理。这意味着,当你使用 Hibernate 进行数据操作时,所涉及的事务要么基于 JDBC 的事务管理,要么...

    Hibernate事务处理

    ### Hibernate事务处理详解 #### 一、事务处理概念与特性 事务处理是数据库操作中一个核心的概念,尤其在处理复杂的业务逻辑时,确保数据的一致性和完整性至关重要。Hibernate作为Java领域中广泛使用的对象关系...

    spring与hibernate的包冲突

    在博文链接中(由于实际链接无法访问,这里只能假设博主讨论了相关问题),作者可能详细解释了如何在Spring和Hibernate共存的环境中识别并解决类冲突。这可能包括查看并分析项目的类路径(classpath),查找重复的...

    hibernate5--2.数据持久化及事务

    **JDBC事务管理:** - `Session.beginTransaction()` 开启事务。 - 对象的CRUD操作。 - `session.getTransaction().commit()` 提交事务。 - `session.getTransaction().rollback()` 回滚事务。 **JTA事务管理:** ...

    hibernate的事务和并发资料.pdf

    首先,Hibernate支持两种类型的事务管理:JDBC连接管理和JTA(Java Transaction API)资源管理。它并未添加额外的锁定行为,而是依赖于数据库的事务隔离级别。自动版本管理是Hibernate提供的一项特性,用于处理并发...

    08JDBC的事务处理.zip

    3. **隔离性**:并发执行的事务之间应相互隔离,避免数据冲突和脏读等问题。 4. **持久性**:一旦事务提交,其结果就是永久性的,即使系统崩溃,数据也应保持不变。 在JDBC中,可以通过以下步骤控制事务: 1. **...

    springboot(4) 整合mybatis和hibernate

    注意,由于同时使用了MyBatis和Hibernate,可能需要调整Spring Boot的数据源配置,避免两者冲突。在实际项目中,可能需要考虑事务管理,确保在一次操作中使用同一种ORM框架。 在启动项目之前,按照描述中的提示,...

    xfire跟spring和hibernate集成例子

    通过这样的集成,我们可以享受到Spring的灵活管理和事务控制,Hibernate的高效持久化,以及XFire的便捷Web服务发布。这样的组合使得开发高质量、可维护的企业级应用变得更加容易。然而,需要注意的是,集成过程中...

    Hibernate性能(缓存 延迟加载 事务 悲观 乐观锁).ppt

    Hibernate支持JTA(Java Transaction API)和JDBC事务管理。通过`session.beginTransaction()`开启事务,`transaction.commit()`提交事务,确保一组操作要么全部成功,要么全部回滚,确保数据的原子性。 **4. ...

    整合struts2.1和hibernate3.2的JAR包

    Struts2和Hibernate是两个非常重要的Java开源框架,它们分别用于MVC(Model-View-Controller)架构的实现和对象关系映射(ORM)。在Java Web开发中,整合这两个框架可以构建高效、灵活且可维护的业务应用。下面将...

    hibernate4基本配置方式详解

    在事务管理方面,Hibernate 支持 JDBC 事务和 JTA(Java Transaction API)事务。为了确保应用程序在不同类型的事务环境中的移植性,你需要正确配置事务策略。 总之,Hibernate 4 的基本配置包括了XML配置文件、...

    hibernate pdf 电子书

    Hibernate支持JDBC的事务管理,并且可以与Spring框架集成,提供声明式事务处理。同时,Hibernate还提供了乐观锁和悲观锁等并发控制策略,以防止数据冲突。你需要理解何时使用事务开始、提交和回滚,以及如何正确地...

    java jdbc 需要包

    8. `spring-orm-3.2.0.M1.jar`: 提供了对ORM(Object-Relational Mapping)框架的支持,如Hibernate和JPA,与Spring JDBC一起,可以实现更高级的数据库操作。 9. `spring-aop-3.2.0.M1.jar`: AOP模块提供了面向切面...

    Hibernate Developer Guide

    ##### 2.3 Hibernate事务使用 在Hibernate中使用事务的典型方法是在Session的生命周期内管理事务。 ##### 2.4 事务性模式(和反模式) **241. 会话/操作反模式** 会话/操作反模式指的是在每个操作都开启一个新的...

    JAVA(Spring)事务管理.doc

    隔离级别是防止并发事务之间数据冲突的重要手段,常见的隔离级别有READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。每种隔离级别对应不同的并发控制策略,以防止脏读、不可重复读和幻读等问题。...

    jee事务控制.pdf

    本文将结合Hibernate和JPA标准,深入探讨J2EE持久层设计中遇到的关键问题之一——事务并发访问控制策略。 #### 二、事务并发访问控制策略概述 事务并发访问控制主要包括两方面:同一个系统事务内的并发控制和跨...

    hibernate框架jar包整合

    当项目使用Spring框架时,可以利用Spring的`HibernateTemplate`或`SessionFactoryBean`来更方便地管理Hibernate的生命周期和事务。 在实际项目中,这些jar包通常会被包含在Maven或Gradle的依赖管理中,避免手动...

Global site tag (gtag.js) - Google Analytics