Spring外部事务失败回滚内部事务

时间:2018-08-20 01:30:40

标签: spring transactional

我有以下使用Spring @Transactional批注的代码。

//in A.java
Class A {
    @Transactional(propagation=propagation.???)
    public void aMethod() {
        B b = new B();
        b.bMethod(); // success and committed
        aPrivateMethod(); // failure
    }

    private void aPrivateMethod() { //something }
}

//in B.java
Class B {
    @Transactional(propagation=propagation.???)
    public void bMethod() { //something }
}

我期望的A.aMethod()行为是:

  

如果b.bMethod()成功并已提交但aPrivateMethod()失败,   然后A.aMethod()会回滚,包括b.bMethod()。

如何设置@Transactional传播参数来实现这一目标?

2 个答案:

答案 0 :(得分:1)

这是结论。

示例1

'password,client_credentials,refresh_token'

示例2

// A.java
class A {
    @Transactional(rollbackFor = Exception.class)
    public void aMethod() {
        B b = new B();
        try {
            b.bMethod("111", false); // bMethod() is NOT rolled back, record of "111" has been created
        } catch (Exception e) {
            // Do nothing, let it go
        }
        b.bMethod("222", true); // record of "222" has been created
    }

    // The annotation below is ignored
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void bMethod(String id, bool success) {
        createRecordInDB(id);
        if (!success) {
            throw new Exception("Throw exception explicitly!");
        }
    }
}

示例3

// A.java
class A {
    @Transactional(rollbackFor = Exception.class)
    public void aMethod() {
        B b = new B();
        b.bMethod("111", true); // record of "111" has been rolled back and NOT created
        b.bMethod("222", true); // record of "222" has been rolled back and NOT created
        createRecordInDB("333"); // record of "333" has been rolled back and NOT created
        throw new Exception("Throw exception explicitly!");
    }

    // The annotation below is ignored
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void bMethod(String id, bool success) {
        createRecordInDB(id);
        if (!success) {
            throw new Exception("Throw exception explicitly!");
        }
    }
}

示例4

// A.java
class A {
    @Transactional(rollbackFor = Exception.class)
    public void aMethod() {
        B b = new B();
        try {
            b.bMethod("111", false); // bMethod() has been rolled back, record of "111" has NOT been created
        } catch (Exception e) {
            // Do nothing, let it go
        }
        b.bMethod("222", true); // record of "222" has been created
    }
}

// B.java
class B {
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void bMethod(String id, bool success) {
        createRecordInDB(id);
        if (!success) {
            throw new Exception("Throw exception explicitly!");
        }
    }
}

答案 1 :(得分:0)

所有已发布的示例将打开一个新的交易环境,而与任何外部交易无关。因此,REQUIRES_NEW仅在此范围内的事务块和回滚更改中起作用。 您只需要提供:

Class A {
    @Transactional(propagation=Propagation.REQUIRED)
    public void aMethod() {
        B b = new B();
        b.bMethod(); // success and committed
        aPrivateMethod(); // failure
    }

    private void aPrivateMethod() { //something }
}