如果B出错,请回滚A。春季引导,jdbctemplate

如果B出错,请回滚A。春季引导,jdbctemplate,第1张

如果B出错,请回滚A。春季引导,jdbctemplate

@Transactional
spring中的注释通过将对象包装在代理中而起作用,代理又包装了
@Transactional
事务中注释的方法。因为该注释不适用于私有方法(如您的示例),因为
私有方法不能被继承
=>它们不能被包装(如果您对Aspectj使用声明式事务,则不正确,然后与代理相关的警告下面不适用)。

这是

@Transactional
d簧魔术原理的基本解释。

你写了:

class A {    @Transactional    public void method() {    }}

但这是您注入bean时实际得到的:

class ProxiedA extends A {   private final A a;   public ProxiedA(A a) {       this.a = a;   }   @Override   public void method() {       try {// open transaction ...a.method();// commit transaction       } catch (RuntimeException e) {// rollback transaction       } catch (Exception e) {// commit transaction       }   }}

这有局限性。它们无法使用

@PostConstruct
方法,因为在代理对象之前调用它们。即使所有配置正确,默认情况下,事务也只会回滚 未检查的
异常。使用
@Transactional(rollbackFor={CustomCheckedException.class})
如果您需要回滚一些检查异常。

我知道的另一个经常遇到的警告:

@Transactional
该方法仅在您从外部调用时才有效,在以下示例中,该方法
b()
不会包装在事务中:

class X {   public void a() {      b();   }   @Transactional   public void b() {   }}

这也是因为

@Transactional
可以通过代理对象来工作。在上面的示例中,
a()
不会调用
X.b()
增强的“ spring
proxy”方法,
b()
因此不会进行任何事务。解决方法是,必须
b()
从另一个bean 调用。

当您遇到以下任何警告并且无法使用建议的解决方法(使方法为非私有方法或

b()
从另一个bean
调用)时,可以使用
TransactionTemplate
而不是声明性事务:

public class A {    @Autowired    TransactionTemplate transactionTemplate;    public void method() {        transactionTemplate.execute(status -> { A(); B(); return null;        });    }...}

更新资料

使用上面的信息回答OP更新的问题。

哪种方法应使用@Transactional:changes()进行注释?databaseChanges()?

@Transactional(rollbackFor={Exception.class})public void changes() throws Exception {    someLogicBefore();    databaseChanges();    someLogicAfter();}

确保

changes()
在bean的外部“调用”,而不是在类本身以及实例化上下文之后调用它(例如,“ not”
afterPropertiesSet()
或“
@PostConstruct
notnotated”方法)。了解默认情况下,春季回滚事务仅适用于未检查的异常(尝试在rollbackFor检查的异常列表中更具体)。



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5164862.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-18
下一篇2022-11-18

发表评论

登录后才能评论

评论列表(0条)

    保存