当前位置: 首页 > 知识库问答 >
问题:

Spring事务传播

杜禄
2023-03-14

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

如果我根据需要使用传播或REQUIRES\u NEW,我会得到错误“非法尝试使用现有的两阶段资源提交一阶段资源”。

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

我的理解是,如果传播=支持/不支持,那么在下面的场景中甚至不会启动事务。因此,这两个插入可能在两个不同的数据库中独立发生,如果其中一个数据库失败,则整个事务不应回滚。

但是传播=支持/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个答案

嵇丰
2023-03-14

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

当您使用“不支持”或“支持”时,它可以正常工作,因为它是非事务性的。参见组织。springframework。交易注释。传播javadoc。

曹驰
2023-03-14

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

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

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

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

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

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

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

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

 类似资料:
  • 所称的刀是: 我希望服务类中的方法在事务中运行,并在方法出现异常时回滚所有内容。但这不是在事务中运行的。 如果我将添加到DAO方法中,那么它看起来就像是在单独的事务中运行的。这是正确的吗?

  • 在下面的文章中说, 在此处输入链接描述 需要传播–支持当前交易;如果不存在,请创建一个新的。 下面是一个产品代码,然后是两个表的产品详细信息。 我的问题是什么时候会发生这种行为?我的意思是,当前交易怎么会结束?是在保存还是更新之后? 如果我们使用PROPAGATION_REQUIRED假设当前事务在插入产品后结束。然后一个新的事务来了,但是如果插入产品数量时出现任何故障,它只会回滚数量而不是输入的

  • 在以下代码方法中,更新正确的sql,但sql有一些问题,但是,当我调用doService()时,它必须将更新提交到DB,即使doService 2()有sql异常,因为doService 2()有一个新的传播类型,但是当我取消这个更新时,不会提交DB。。 正如你们的建议,以以下方式进行测试,但仍然面临相同的问题。这里i在一个单独的类中,但即使仍然存在与上述相同的问题

  • 本文向大家介绍浅谈Spring事务传播行为实战,包括了浅谈Spring事务传播行为实战的使用技巧和注意事项,需要的朋友参考一下 Spring框架提供了事务管理的标准实现,且可以通过注解或者XML文件的方式声明和配置事务。 通过异步事件的方式解耦服务调用,可以提高程序的响应速度,并且避免因为事务传播行为而导致的事务问题。 本文以一个电商平台包裹出库的业务为实际背景,通过异步事件与线程池的方式解耦嵌套

  • 当somehelper类中的任何方法(将传播行为设置为“requires_new”的事务块)中出现某些异常时,为什么调用方类中不处理它(具有默认传播行为的事务块)?我看到的不是消息“catch inside doOperationMetadata of Impl class”,而是消息“catch inside callServiceMethod of Controller class”。

  • 当外部方法运行时,它调用内部方法。运行内部方法时,外部方法暂停。一旦内部方法完成,它就被提交,因为它是一个不同的事务。外部方法取消暂停。并且它也作为另一个事务提交。 我遇到的问题是,提交外部方法的过程会触发子类的乐观锁定(可能是因为在内部方法结束并提交之后,版本字段的值发生了更改)。由于外部方法的Child实例已经过时,提交它将触发乐观锁定。 我的问题是:有没有一种方法可以防止外部方法触发乐观锁定