春季@Transactional继承规则

2022-09-01 23:45:21

我有一组从抽象类继承核心功能的bean。我用 和 标记了每个具体的子类服务。抽象超类包含其中每个服务的公共入口点方法。换句话说,我有类似于以下内容的东西:@Service@Service@Transactional

abstract class AbstractService {

    public void process() {
        // Do common initialisation code here
        processSpecific();
        // Do common completion code here
    }

    abstract protected void processSpecific();
}


@Service @Transactional
public class FirstSpecificService extends AbstractService {
    protected void processSpecific() {
        // Do specific processing code here
    }
}


@Service @Transactional
public class SecondSpecificService extends AbstractService {
    protected void processSpecific() {
        // Do different specific processing code here
    }
}

每个具体子类服务中的特定代码对 DAO 层进行多次调用,以对数据库进行更改,这些更改具有事务传播类型。REQUIRED

现在,使用如上所述定义的服务,我发现这些具体子类服务的任何代码中都没有当前事务,并且对DAO层的每次调用都在创建一个新事务,进行更改,提交事务并返回。

但是,如果我用 注释抽象超类,则正确创建事务,并且对 DAO 层的子调用都参与当前事务。@Transactional

所以我的问题是,继承行为的规则是什么?为什么Spring没有使用它实际实例化的具体子类服务?在这种情况下,是否需要在超类上,因为这是公共入口点方法的位置?@Transactional@Transactional@Transactional


答案 1

从春季交易文件中,

注意:在代理模式(这是默认设置)中,只有通过代理传入的“外部”方法调用才会被拦截。这意味着“自调用”,即目标对象中的方法调用目标对象的其他方法,即使调用的方法被标记为@Transactional,也不会在运行时导致实际的事务!

即使你有@Transactional你的具体实现,并且你正在调用你的注释实际上是事务性的进程方法,但是由于这个内部调用,在你的子类上调用processSpecific的处理方法不是事务性的。

看看编织。


答案 2

您是否阅读了有关事务传播以及如何使用@Transactional配置事务传播的部分?

另一个有趣的领域是,Spring建议你应该注释具体的类(与注释接口相反)。


推荐