Spring 事务注解 @Transactional
一、使用@Transactional
Describes a transaction attribute on an individual method or on a class.
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.
This annotation type is generally directly comparable to Spring’s org.springframework.transaction.interceptor.RuleBasedTransactionAttribute class, and in fact AnnotationTransactionAttributeSource will directly convert the data to the latter class, so that Spring’s transaction support code does not have to know about annotations. If no rules are relevant to the exception, it will be treated like org.springframework.transaction.interceptor.DefaultTransactionAttribute (rolling back on RuntimeException and Error but not on checked exceptions).
For specific information about the semantics of this annotation’s attributes, consult the TransactionDefinition and org.springframework.transaction.interceptor.TransactionAttribute javadocs.
Used at the class level as above, the annotation indicates a default for all methods of the declaring class (as well as its subclasses). Alternatively, each method can be annotated individually. See null for further details on which methods Spring considers transactional. Note that a class-level annotation does not apply to ancestor classes up the class hierarchy; in such a scenario, inherited methods need to be locally redeclared in order to participate in a subclass-level annotation.
该注解在类上使用时,默认应用给在这个类中声明的所有方法,同时也应用于此类的子类。
注意:对于在类层级结构中该类的父类,此注解是不生效的。子类中继承父类的方法需要在子类中重新声明才能使子类上的事务注解生效。
Method visibility and
@Transactional
in proxy modeThe
@Transactional
annotation is typically used on methods withpublic
visibility. As of 6.0,protected
or package-visible methods can also be made transactional for class-based proxies by default. Note that transactional methods in interface-based proxies must always bepublic
and defined in the proxied interface. For both kinds of proxies, only external method calls coming in through the proxy are intercepted.
@Transactional
注解通常作用于 public
修饰的方法。从spring 6.0开始,protected
或包访问权限的方法在默认情况下也能使基于类的代理具有事务。
注意:基于接口的代理中的事务方法必须总是以 public
修饰的,并且在被代理的接口中进行定义。
在这两种代理中(基于类的和基于接口的),只拦截通过代理传入的外部方法调用。
The Spring team recommends that you annotate only concrete classes (and methods of concrete classes) with the
@Transactional
annotation, as opposed to annotating interfaces. You certainly can place the@Transactional
annotation on an interface (or an interface method), but this works only as you would expect it to if you use interface-based proxies. The fact that Java annotations are not inherited from interfaces means that, if you use class-based proxies (proxy-target-class="true"
) or the weaving-based aspect (mode="aspectj"
), the transaction settings are not recognized by the proxying and weaving infrastructure, and the object is not wrapped in a transactional proxy.
spring团队推荐将 @Transactional
注解只是应用在具体的类上面,而不是接口上面。除非。。。
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object calling another method of the target object) does not lead to an actual transaction at runtime even if the invoked method is marked with
@Transactional
. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code — for example, in a@PostConstruct
method.
在代理模式(这是默认模式)下,只有通过代理传入的外部方法调用才会被拦截。这意味着自调用(实际上,目标对象中的一个方法调用目标对象的另一个方法)在运行时不会导致实际事务,即使调用的方法标记为@Transactional。此外,代理必须完全初始化才能提供预期的行为,因此您不应该在初始化代码中依赖此功能 — 例如在@PostConstruct方法中。
@EnableTransactionManagement
and<tx:annotation-driven/>
look for@Transactional
only on beans in the same application context in which they are defined. This means that, if you put annotation-driven configuration in aWebApplicationContext
for aDispatcherServlet
, it checks for@Transactional
beans only in your controllers and not in your services. See MVC for more information.
@EnableTransactionManagement
和 <tx:annotation-driven/>
仅在定义它们的同一应用程序上下文中的bean上查找@Transactional
。这意味着,如果您将注释驱动的配置放在 DispatcherServlet
的 WebApplicationContext
中,它只会在控制器中检查 @Transactional
beans,而不会在服务中检查。
The most derived location takes precedence when evaluating the transactional settings for a method.
方法和类上同时使用了 @Transactional
注解,则方法上的注解优先级更高。
二、@Transactional
设置
设置的默认值如下:
- 传播机制默认为
REQUIRED
- 隔离级别默认为
DEFAULT
,即采用数据源隔离级别的默认配置 - 读写事务
- 事务超时时间默认为事务系统的默认超时时间,如果不支持超时时间,则无
- 任何运行时异常或
Error
都会触发回滚,检查时异常则不会。
1、Propagation传播机制
2、Isolation隔离级别
适用于传播行为中的 REQUIRED
和 REQUIRED_NEW
,因为它只适用于新启动的事务。REQUIRED
在没有事务时会新建事务,而 REQUIRED_NEW
则会始终新建事务。
该配置中的可选项有:
- DEFAULT,使用数据源的默认隔离级别。
- READ_UNCOMMITTED
- READ_COMMITTED
- REPEATABLE_READ
- SERIALIZABLE
3、timeout
此事务的超时时间,单位秒
适用于传播行为中的 REQUIRED
和 REQUIRED_NEW
,因为它只适用于新启动的事务。
4、readOnly
如果事务是只读的,那么可以将此配置设置为 true,从而允许在运行时进行相应的优化。默认为false。
这只是对事务管理器的提醒,当配置此属性为 true,但是进行了写尝试时,并不会抛出异常,事务管理器只会忽略掉。
适用于传播行为中的 REQUIRED
和 REQUIRED_NEW
,因为它只适用于新启动的事务。
5、rollbackFor
导致事务回滚的异常Class数组,这些异常类型必须是 Throwable
的子类。
默认情况下,事务将在产生 RuntimeException
和 Error
时回滚,但不会在产生编译异常时回滚。
相比于 rollbackForClassName
此配置是更推荐的,因为可以以类型安全的方式匹配异常类及其子类。
参见:org.springframework.transaction.interceptor.DefaultTransactionAttribute.rollbackOn(Throwable ex)
1 |
|
6、rollbackForClassName
导致事务回滚的异常类名数组
7、noRollbackFor
不会导致事务回滚的异常Class数组,这些异常类型必须是 Throwable
的子类。
相比于 noRollbackForClassName
此配置是更推荐的,因为可以以类型安全的方式匹配异常类及其子类。
8、noRollbackForClassName
不会导致事务回滚的异常类名数组
三、@Transactional
使用多事务管理器
四、定制组合注解
相关链接
Using @Transactional :: Spring Framework
OB links
[[Propagation 传播机制]]
[[事务隔离级别]]
OB tags
#事务 #Spring #未完待续