简体   繁体   English

Spring @Transactional 继承规则

[英]Spring @Transactional inheritance rules

I have a set of @Service beans which inherit core functionality from an abstract class.我有一组从抽象类继承核心功能的@Service bean。 I marked each of the concrete sub-class services with @Service and @Transactional .我用@Service@Transactional标记了每个具体的子类服务。 The abstract super class contains the public entry point method for each of these services.抽象超类包含每个服务的公共入口点方法。 In other words, I have something similar to the following:换句话说,我有类似的东西:

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
    }
}

The specific code in each concrete sub-class service makes multiple calls to the DAO layer to make changes to the database, which have REQUIRED as the transactional propagation type.每个具体子类服务中的特定代码对 DAO 层进行多次调用,以对数据库进行更改,其中REQUIRED作为事务传播类型。

Now with the services defined as above, I discovered that there was no current transaction inside any of the code of these concrete sub-class services, and each call to the DAO layer was creating a new transaction, doing the changes, committing the transaction and returning.现在有了上面定义的服务,我发现在这些具体的子类服务的任何代码中都没有当前事务,每次调用 DAO 层都在创建一个新事务,进行更改,提交事务和回来。

However, if I annotate the abstract super-class with @Transactional , then a transaction is created properly, and the sub-calls to the DAO layer all participate in the current transaction.但是,如果我用@Transactional注释抽象超类,那么正确创建了一个事务,并且对 DAO 层的子调用都参与了当前事务。

So my question is, what are the rules for inheriting the @Transactional behaviour?所以我的问题是,继承@Transactional行为的规则是什么? Why does Spring not use the @Transactional on the concrete sub-class services that it is actually instantiating?为什么 Spring 不在它实际实例化的具体子类服务上使用@Transactional Does the @Transactional need to be on the super-class in this case because that is where the public entry-point method is?在这种情况下,@ @Transactional是否需要位于超类上,因为这是公共入口点方法所在的位置?

From the spring transaction documentation,从 spring 交易文档中,

Note: In proxy mode (which is the default), only 'external' method calls coming in through the proxy will be intercepted.注意:在代理模式下(默认),只有通过代理进入的“外部”方法调用才会被拦截。 This means that 'self-invocation', ie a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with @Transactional!这意味着“自调用”,即目标对象中的一个方法调用目标对象的其他方法,即使被调用的方法用@Transactional 标记,也不会在运行时导致实际的事务!

Even though you have the @Transactional on your concrete implementation and you are calling process method which is actually transactional by your annotation, but the process method calling processSpecific on your sub class is not transactional because of this internal call.即使你在你的具体实现上有 @Transactional 并且你正在通过你的注释调用实际上是事务性的 process 方法,但是由于这个内部调用,在你的子类上调用 processSpecific 的 process 方法不是事务性的。

Look into Weaving.看看织布。

Did you read the part about transaction propagation and how it can be configured using @Transactional ?您是否阅读了有关事务传播以及如何使用@Transactional对其进行配置的部分?

Another area of interest is that Spring recommends that you should annotate concrete classes (as opposes to annotate interfaces).另一个有趣的领域是 Spring 建议您应该注释具体类(与注释接口相反)。

This is an old question.这是一个老问题。 But I ran into a similar situation and found the explanation in the current javadoc for the @Transactional annotation:但是我遇到了类似的情况,并在当前的 javadoc 中找到了 @Transactional 注释的解释:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html

At the class level, this annotation applies as a default to all methods of the declaring class and its subclasses.在类级别,此注释默认应用于声明类及其子类的所有方法。 Note that it does not apply to ancestor classes up the class hierarchy;请注意,它不适用于在类层次结构中向上的祖先类; methods need to be locally redeclared in order to participate in a subclass-level annotation.方法需要在本地重新声明才能参与子类级别的注释。

So, when using inheritance and class level annotation you should annotate the super class and not the sub classes if the super class contains any public methods that should be transactional or do call methods implemented by the sub classes that need to be transactional.因此,当使用继承和类级别注释时,如果超类包含任何应该是事务性的公共方法或调用需要事务性的子类实现的方法,则应该注释超类而不是子类。

Calling methods which are implemented and annotated @Transactional by the subclasses from methods in the super class without the super class or that method being annotated @Transactional is a bug.从超类中的方法调用子类实现和注释@Transactional 的方法,而没有超类或该方法被注释@Transactional 是一个错误。 And if both are annotated but the attributes on the annotation are inconsistent that is also a bug.如果两者都被注释但注释上的属性不一致,这也是一个错误。

In a good design virtual methods in the super class which are implemented by subclasses should be used by the super class only and they should because of that always have scope protected and never need any @Transactional annotation in the sub class在一个良好的设计中,由子类实现的超类中的虚拟方法应该只由超类使用,因为它们应该始终具有范围保护并且从不需要子类中的任何 @Transactional 注释

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM