有一点不同。假设我们有两个方法a() 和b(),而a() 将调用b()。 a本身是跨国的,它的传播等级是Propagation.REQUIRED,但是b有一次被@Transactional(propagation = Propagation.SUPPORTS)注解,一次没有被注解。
案例一:
@Transactional
public void a() {
for (int i = 0; i < 10; i++) {
try {
productRepository.b(i, "product " + i);
} catch (RuntimeException ex){
// do nothing
}
}
}
public void b(int id, String name) {
if(id > 5)
throw new RuntimeException();
String sql = "INSERT INTO test_table VALUES(?, ?)";
template.update(sql, id, name);
}
在情况 1 中,我们有 aspect() -> a() -> b() 并且您可以阻止 RuntimeException 到达方面,方面检查事务以查看它是否标记为回滚,因此方面认为此事务成功,您可以看到我们有这个结果在我们的数据库中
0,product 0
1,product 1
2,product 2
3,product 3
4,product 4
5,product 5
即使抛出了多个异常,但我们能够提交到目前为止已经完成的操作。
现在考虑案例 2:
@Transactional
public void a() {
for (int i = 0; i < 10; i++) {
try {
productRepository.b(i, "product " + i);
} catch (RuntimeException ex){
// do nothing
}
}
}
@Transactional(propagation = Propagation.SUPPORTS)
public void b(int id, String name) {
if(id > 5)
throw new RuntimeException();
String sql = "INSERT INTO test_table VALUES(?, ?)";
template.update(sql, id, name);
}
propagation = Propagation.SUPPORTS 如果事务已经存在,它将使用它。因此,如果您在 b 中抛出异常,它将标记相同的事务以回滚,即使您使用 try/catch 块来阻止 RuntimeException 到达 a() 中的方面,事务已经被标记为回滚在b 中,您在数据库中看不到任何结果。 aspect() -> a() -> aspect() -> b()
感谢 Laurentiu Spilca,请参阅 this 并阅读评论部分