一尘不染

Spring @Transactional批注:自我调用

hibernate

我知道从同一个类内部调用事务方法时,它不会在事务中运行。Spring为事务方法创建代理,并将它们包装在try-
catch块中,如果发生异常,则回滚。请考虑以下情形:

@Transactional
public void saveAB(A a, B b)
{
    saveA(a);
    saveB(b);
}

@Transactional
public void saveA(A a)
{
    dao.saveA(a);
}

@Transactional
public void saveB(B b)
{
    dao.saveB(b);
}

假设saveAB已从另一个对象调用,并且中发生了异常saveB,因此saveA成功完成但未成功saveB。据我所知,尽管saveA并且saveB不是事务性的(因为它们是从同一个对象中调用的),但由于saveAB它是事务性的,因此仍应回滚。

我不明白的是,为什么人们说自我调用会破坏交易?只要调用方方法是事务性的,所有的事情就不应该按预期工作吗?我在这里想念什么吗?


阅读 376

收藏
2020-06-20

共1个答案

一尘不染

我不明白的是,为什么人们说自我调用会破坏交易?

我从未听说过自调用会中断事务。我所知道的是,自调用不会启动新事务,您已经提到了原因。

Spring交易管理规范的摘录

注意
在代理模式(默认设置)下,仅拦截通过代理传入的外部方法调用。这意味着,实际上,即使被调用的方法标有@Transactional,自调用实际上也不会导致运行时实际事务在目标对象中调用目标对象的另一种方法。


如果@Transaction从中删除注释saveAB(),则将观察该方法saveA()saveB()即使使用注释,也不会在事务下运行@Transactional。但是,如果您在类外部调用saveA()saveB()从类外部调用,它将按预期在事务下运行。这就是为什么人们建议对自调用要谨慎的原因。

public void saveAB(A a, B b)
{
    saveA(a);
    saveB(b);
}

@Transactional
public void saveA(A a)
{
    dao.saveA(a);
}

@Transactional
public void saveB(B b)
{
    dao.saveB(b);
}

我认为,自行调用任何公共方法都是一个坏主意。

2020-06-20