春季交易传播

时间:2014-05-05 21:48:43

标签: spring transactions propagation

我试图了解Spring Transaction概念。如下所示,我将数据插入两个不同的数据库(iSeries和DB2),但我们的iSeries版本不支持两阶段提交。要求是,只有在两个插入成功的情况下才应该提交Transaction,否则它应该回滚。

如果我将传播用作REQUIRED或REQUIRES_NEW,我会收到错误"非法尝试使用现有的两阶段资源提交具有单阶段功能的资源"。

但是如果我使用NOT_SUPPORTED或SUPPORTS,它可以正常工作(例如,如果其中一个Insert失败,则事务回滚,否则如果两个Insert都成功则提交。)

我的理解是,如果Propagation = SUPPORTS / NOT_SUPPORTED,那么即使在下面的场景中也无法启动交易。因此,两个插入可能在两个不同的数据库中独立发生,并且如果其中一个数据库失败,则整个事务不应该回滚。

但是Propagation = SUPPORTS / NOT_SUPPORTED按照我的要求工作。有人可以解释一下吗?提前谢谢。

@Resource
private SessionFactory db2SessionFactory = null;

@Resource
private SessionFactory iSeriesSessionFactory = null;

@Transactional(propagation = Propagation.REQUIRED)
public void insert()
{
   insertDB1();
   insertDB2();
}

insertDB1()
{
   db2SessionFactory .getCurrentSession().saveOrUpdate(obj1);
}

insertDB2()
{
   iSeriesSessionFactory.getCurrentSession().saveOrUpdate(obj2);
}

2 个答案:

答案 0 :(得分:1)

好的,我会解释一下我的想法。我强调,这是我的假设。可能是我完全错了。

首先,我从来没有必要为@Transactional注释指定传播。要求是一个很好的标准。如果您遇到异常,通常是因为您没有正确操作数据库。然而,这可能不是这种情况,因为我以前从未使用过多个会话工厂。

我认为当您指定SUPPORTS或NOT_SUPPORTED时发生的事情是保存是非事务性的发生仅仅因为保存是非事务性的,它并不意味着如果发生某种类型的错误,整个会话不会回滚,因为这显然正在发生的事情。

当您使用REQUIRED或REQUIRES_NEW时,您正在创建一个新事务,每个事务都有自己的JDBC连接(显然),但使用相同的事务会话。这就是你获得illegal attempt例外的原因。已为两阶段资源创建了transactional会话,但您尝试使用相同的会话保存到单阶段数据库。

如果您有2个注释@Transactional的方法,其中一个方法调用另一个方法,那么传播真的只会发挥作用:

@Transactional
public void method1(){
    method2();
}

@Transactional
public void method2(){
    //do some transactional stuff here
}

您的传播级别将确定是否创建了方法1的新会话,是否将现有会话用于方法2,是否为方法2创建了新会话,或者是否以非事务方式执行了整个事务。

答案 1 :(得分:0)

JTA支持两阶段提交事务。检查您是否使用JtaTransactionManager

使用NOT_SUPPORTEDSUPPORTS时效果很好,因为它非事务性地工作。请参阅org.springframework.transaction.annotation.Propagation javadoc。