我有以下嵌套事务的服务布局:
@Component
public class Main implements RPCInterface {
@Autowired
private ServiceA serviceA;
@Autowired
private ServiceB serviceB;
@Autowired
private ServiceC serviceC;
@Override
@Transactional (value="txManager", propagation=Propagation.REQUIRED, rollbackFor={ExceptionOne.class, ExceptionTwo.class, ExceptionThree.class})
public void outerMethod() throws ExceptionO {
try {
serviceA.methodA();
serviceB.methodB();
serviceC.methodC();
} catch (ExceptionOne e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionTwo e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionThree e) {
throw new ExceptionO(e.getMessage, e);
}
}
}
@Service
public class ServiceA implements SA {
@Autowired
private ServiceA1 serviceA1;
@Override
public void methodA() {
serviceA1.methodA1();
}
}
@Service
public class ServiceA1 implements SA1 {
@Autowired
private ServiceDBTable1 serviceDBTable1;
@Autowired
private ServiceA1A serviceA1A;
@Transactional
@Override
public void methodA1() {
serviceDBTable4.callToMapper4();
serviceA1A.methodA1A();
}
}
@Service
@Transactional (value="txManager", propagation=Propagation.REQUIRED)
public class ServiceA1A implements SA1A {
@Autowired
private ServiceDBTable2 serviceDBTable2;
@Override
public void methodA1A() {
serviceDBTable1.callToMapper1();
}
}
@Service
public class ServiceB implements SB {
@Autowired
private ServiceDBTable3 serviceDBTable3;
@Override
@Transactional (value="txManager", propagation=Propagation.REQUIRED)
public void methodB() {
serviceDBTable3.callToMapper3();
}
}
@Service
public class ServiceC implements SC {
@Override
public void methodC() throws ExceptionThree {
// code that throws ExceptionThree
}
}
当 ServiceC#methodC()
抛出异常时,我需要在 ServiceA
和 ServiceB
嵌套调用中进行所有数据库调用以回滚(或其中任何抛出异常的项 - ServiceA
或 ServiceB
)。
我尝试使用 REQUIRED
传播使 Main#outerMethod
事务化,但数据库提交似乎没有回滚。我什至用 rollbackFor
指定了特定的类,但提交仍然存在。有谁知道如何解决这个问题吗?
最佳答案
为了使其正常工作,我所做的是将 ServiceB.methodB()
和 ServiceC.methodC()
调用迁移到 ServiceA.methodA()
code>,并创建 methodA()
@Transactional
,同时从 methodA()
抛出所有异常,并根据这三个异常进行回滚(我的逻辑实际上允许我这样做):
@Component
public class Main implements RPCInterface {
@Autowired
private ServiceA serviceA;
@Override
public void outerMethod() throws ExceptionO {
try {
serviceA.methodA();
} catch (ExceptionOne e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionTwo e) {
throw new ExceptionO(e.getMessage, e);
} catch (ExceptionThree e) {
throw new ExceptionO(e.getMessage, e);
}
}
}
@Service
public class ServiceA implements SA {
@Autowired
private ServiceA1 serviceA1;
@Autowired
private ServiceB serviceB;
@Autowired
private ServiceC serviceC;
@Override
@Transactional (value="txManager", propagation=Propagation.REQUIRED, rollbackFor={ExceptionOne.class, ExceptionTwo.class, ExceptionThree.class})
public void methodA() throw ExceptionOne, ExceptionTwo, ExceptionThree {
serviceA1.methodA1();
serviceB.methodB();
serviceC.methodC();
}
}
@Service
public class ServiceA1 implements SA1 {
@Autowired
private ServiceDBTable1 serviceDBTable1;
@Autowired
private ServiceA1A serviceA1A;
@Transactional
@Override
public void methodA1() {
serviceDBTable4.callToMapper4();
serviceA1A.methodA1A();
}
}
@Service
@Transactional (value="txManager", propagation=Propagation.REQUIRED)
public class ServiceA1A implements SA1A {
@Autowired
private ServiceDBTable2 serviceDBTable2;
@Override
public void methodA1A() {
serviceDBTable1.callToMapper1();
}
}
@Service
public class ServiceB implements SB {
@Autowired
private ServiceDBTable3 serviceDBTable3;
@Override
@Transactional (value="txManager", propagation=Propagation.REQUIRED)
public void methodB() {
serviceDBTable3.callToMapper3();
}
}
@Service
public class ServiceC implements SC {
@Override
public void methodC() throws ExceptionThree {
// code that throws ExceptionThree
}
}
关于java - 在 Spring 中回滚嵌套事务中的所有数据库提交,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42708516/