为什么DataSourceTransactionManage在HibernateTransactionManager执行时不会回滚?

时间:2014-05-26 08:05:25

标签: java spring hibernate

<bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        lazy-init="true">
        <property name="dataSource" ref="dataSource" />
    </bean>

使用spring和hibernate构建应用程序时,如果我使用DataSourceTransactionManager,那么在异常时,它不会回滚。好像它在不同的会话中使用auto-comit。但是,如果我将事务管理器更改为org.springframework.orm.hibernate3.HibernateTransactionManager,则回滚将按预期工作。 或者,如果我们使用hibernate,那么我们需要使用HibernateTransactionManager吗?

N.b:我的服务使用@Transactional(rollbackFor = { Throwable.class} )

注释

2 个答案:

答案 0 :(得分:3)

使用普通休眠时,需要以下内容来管理事务

Session s = sessionfactory.openSession();
Transaction tx = null;
try {
tx = s.beginTransaction();
// Your data manipulation here
tx.commit();
} catch (Exception e) {
if (tx != null) { tx.rollback();}
} finally {
s.close();
}

这也是HibernateTransactionManager的作用(如果需要,打开会话,启动事务,然后提交/回滚)。

现在你要做的是以下(这是DataSourceTransactionManager的类似物,它对`DataSource而不是会话进行操作。)

Session s = sessionfactory.openSession();
Connection conn = null;
try {
    conn = s.connection();
    // Your data manipulation here
    conn.commit();
} catch (Exception e) {
    if (conn != null) { 
        try {
            conn.rollback();
        catch (IOExceptin) {}
    }
} finally {
    s.close();
}

这不会起作用,因为实际的事务单元会话永远不会被告知提交或回滚。因此,在最坏的情况下,根据您的刷新模式,所有(或部分)都会被提交。

简而言之,始终使用适合您技术的交易管理器。

使用普通休眠时使用HibernateTransactionManager,在使用JPA时使用JpaTransactionManager,请不要在这些情况下使用DataSourceTransactionManager,因为只有在的情况下才可以使用Session只使用普通JDBC。

DataSourceTransactionManager明确指出它在DataSource和底层连接上运行。当一个人使用Hibernate时,事务由休眠EntityManager控制,这是HibernateTransactionManager操作的级别。对于JPA,这是{{1}},这是JpaTransactionManager认可的内容。

答案 1 :(得分:0)

根据Spring documentation

  

PlatformTransactionManager实现通常需要知识   他们工作的环境:JDBC,JTA,Hibernate等   上。

     

如果在Java EE容器中使用JTA,则使用容器   DataSource,通过JNDI获得,与Spring一起获得   的JtaTransactionManager。

     

您也可以轻松使用Hibernate本地交易......

     

在这种情况下,您需要定义一个Hibernate LocalSessionFactoryBean,   您的应用程序代码将用于获取Hibernate Session   实例...在这种情况下是HibernateTransactionManager类型。

     

与DataSourceTransactionManager需要引用的方式相同   对于DataSource,HibernateTransactionManager需要一个引用   到SessionFactory。

虽然:

  

DataSourceTransactionManager将绑定JDBC连接   指定DataSource到当前线程,可能允许   一个线程绑定的每个DataSource连接。

会话不会受到当前交易的约束,您需要两者进行本地交易。

这就是hibernate或JPA特定的TM会为您做的事情。它们将关联持久化上下文和每个线程的每个事务一个连接。

如果您选择JTA交易,则外部TM将协调交易。数据库连接将在每个语句之后积极释放,只要外部TM在全局事务生命周期内始终将相同的连接返回到同一个线程,这就很好。