@Transactional(propagation = Propagation.SUPPORTS)方法和没有@Transactional注释的方法有什么区别?
@Transactional(propagation = Propagation.SUPPORTS)
public void MyMethod()vs
public void MyMethod()如果一个事务已经打开,那么没有注释的不会也使用一个事务,否则继续没有任何事务?
发布于 2021-08-30 07:47:30
差别很小。假设我们有两个方法a()和b(),a()将调用b()。a本身是跨国界的,其传播级别为Propagation.REQUIRED,但b一次用@Transactional(propagation = Propagation.SUPPORTS)注释,一次没有注释。
案例1:
@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,请参阅这,并阅读评论部分。
发布于 2019-09-23 04:46:18
从您的链接中,它指出Propagation.SUPPORTS可能会对同步产生影响:
支持与根本没有事务略有不同,因为定义了同步将应用于的事务范围。因此,相同的资源(JDBC连接、Hibernate会话等)将在整个指定的范围内共享。
发布于 2019-09-23 04:50:26
是的,如果一个事务已经打开,没有任何注释的人将使用现有的事务,但是如果没有,那么如果您的事务失败了,您不希望恢复更改。
传播还具有其他属性,以防您的方法不依赖于父事务,并且在单个事务范围内运行,您可能可以选择新的,这样您就可以为您的方法拥有独立的事务。
https://stackoverflow.com/questions/58055761
复制相似问题