Spring事务传播

Spring事务传播,spring,transactions,propagation,Spring,Transactions,Propagation,我试图理解Spring事务的概念。如下所示,我必须将数据插入两个不同的数据库(iSeries和DB2),但我们的iSeries版本不支持两阶段提交。要求是,只有当两个插入都成功时,才应该提交事务,否则应该回滚 如果我根据需要使用传播,或者需要新的传播,我会得到错误“已发生非法尝试使用现有的支持两个阶段的资源提交支持一个阶段的资源” 但是,如果我使用NOT_SUPPORTED或SUPPORTS,它可以正常工作(即,如果其中一个插入失败,事务将回滚,否则如果两个插入都成功,事务将提交) 我的理解是,

我试图理解Spring事务的概念。如下所示,我必须将数据插入两个不同的数据库(iSeries和DB2),但我们的iSeries版本不支持两阶段提交。要求是,只有当两个插入都成功时,才应该提交事务,否则应该回滚

如果我根据需要使用传播,或者需要新的传播,我会得到错误“已发生非法尝试使用现有的支持两个阶段的资源提交支持一个阶段的资源”

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

我的理解是,如果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);
}

好吧,我来解释一下我认为正在发生的事情。我强调,这是我的假设。也许我完全错了

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

当您指定支持或不支持时,我认为发生的情况是,保存是以非事务方式进行的,只是因为保存是以非事务方式进行的,这并不意味着如果发生某种类型的错误,整个会话将不会回滚,因为这显然是正在发生的情况

当您使用REQUIRED或REQUIRES_NEW时,您正在创建一个新事务,每个事务都有自己的JDBC连接(显然),但使用相同的事务会话。这就是为什么您会遇到
非法尝试
异常。已为两阶段资源创建了
事务性
会话,但您正试图使用同一会话保存到一阶段数据库

只有当您有两个带注释的
@Transactional
方法,其中一个方法调用另一个方法时,传播才真正起作用:

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

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

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

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


当您使用
不受支持
支持
时,它可以正常工作,因为它是非事务性工作的。参见
org.springframework.transaction.annotation.Propagation
javadoc.

非常感谢James的回答。。虽然我部分同意你的分析,但我对交易仍不清楚。。但无论如何,这也有点棘手。。再次感谢!!谢谢Sealter,我去查一下javadoc。