如果内部事务失败但内部事务应该保存数据,如何回滚外部事务

时间:2019-05-15 06:48:20

标签: java spring spring-transactions

试图防止内部事务回滚。如果内部事务响应未成功,则外部事务应回滚,但内部事务应保存数据。

BWDisplay::setTemplate($template, array $params = array(), $locale = null)

2 个答案:

答案 0 :(得分:2)

将内部事务方法配置为Propagation.REQUIRES_NEW,以便在方法完成外部事务方法是否回滚时,它将始终提交(即保存数据)。

还要确保外部方法不会自行调用内部方法,因为@Transactional在这种情况下不起作用(请参阅docs中的方法可见性和@Transactional部分)。

它们应该驻留在外部方法调用内部方法的bean的不同bean中:

@Service
public class Service1 {

    @Autowired
    private Service2 service2;

    @Transactional(rollbackFor=Exception.class)
    public void test1(Account account) throws Exception {
        DOA.save(account);
        status = service2.test2(account);
        if(status!='SUCCESS'){
            throw new Exception("Api call failed");
        }
    }
}

@Service
public class Service2{

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void test2(Account account) {
        response // API Call
        DOA.save(response);
        return response.status;
    }
}

答案 1 :(得分:0)

您的@Transactional方法将忽略

Test2,并且该调用是单个事务的一部分。

Spring文档所说的两件事-

方法可见性和@Transactional

  

使用代理时,应应用@Transactional批注   仅适用于具有公众知名度的方法。如果您做受保护的注释,   带有@Transactional批注的私有或包可见方法   不会引发任何错误,但是带注释的方法不会显示   配置的交易设置。考虑使用AspectJ(请参阅   下面)是否需要注释非公共方法。

代理模式

  

在代理模式(默认)下,仅外部方法调用   通过代理进入的邮件被拦截。这意味着   自我调用实际上是目标对象内的一种方法   目标对象的另一种方法,不会导致实际   运行时的事务,即使被调用的方法标记有   @Transactional。

如果要保存内部方法的数据,则可以选择为Test2方法启动新事务,这样就不会影响由Test1开始的现有事务。

但是,即使您公开Test2来自同一类的调用,它也不会启动新事务。

解决方案-

  1. 您可以在事务设置中使用Aspectj模式来为内部方法启动新事务。
  2. 将内部方法重构为另一个组件的一部分,并标记Propagation.REQUIRES_NEW
  3. 手动开始交易Programmatically start new transaction