Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在内部事务失败的情况下如何回滚外部事务,但内部事务应保存数据_Java_Spring_Spring Transactions - Fatal编程技术网

Java 在内部事务失败的情况下如何回滚外部事务,但内部事务应保存数据

Java 在内部事务失败的情况下如何回滚外部事务,但内部事务应保存数据,java,spring,spring-transactions,Java,Spring,Spring Transactions,试图防止内部事务回滚。若内部事务响应未成功,则外部事务应回滚,但内部事务应保存数据 @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW) private void test1(Account account) throws Exception { DOA.save(account); status = test2(account); if(status!='SUC

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

@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRES_NEW)
private void test1(Account account) throws Exception {
    DOA.save(account);
    status = test2(account);
    if(status!='SUCCESS'){
        throw new Exception("api call failed");
    }
}
@Transactional(propagation=Propagation.MANDATORY)
private void test2(Account account) {
    response //API Call
    DOA.save(response);
    return response.status;
}

将内部事务方法配置为
传播。需要\u NEW
,以便无论外部事务方法是否回滚,在方法完成时始终提交(即保存数据)

另外,确保外部方法不会自调用内部方法,因为
@Transactional
在这种情况下不起作用(请参阅中的方法可见性和@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;
    }
}

@Transactional
对于您的
Test2
方法被忽略,并且调用是单个事务的一部分

这里需要考虑的两个问题是“春天博士”——

方法可见性和@Transactional

使用代理时,应应用@Transactional注释 仅适用于具有公共可见性的方法。如果您确实注释了protected, 带有@Transactional注释的私有或包可见方法, 不会引发错误,但带注释的方法不会显示 已配置事务设置。考虑AspectJ的使用(参见 下面)如果需要注释非公共方法

代理模式

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

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

但是在您的情况下,它不会启动新事务,即使您使
Test2
public,因为它是从同一个类调用的

解决方案-

  • 您可以在事务设置中使用aspectj模式为内部方法启动新事务
  • 将内部方法重构为另一个组件的一部分,并标记
    传播。需要\u NEW
  • 手动启动事务

  • @ USER 327 751高兴听到,所以考虑接受我的回答还是给我一个表决?