This article mainly introduces relevant information about the detailed usage of @Transactional in Spring. Friends who need it can refer to the following
Detailed introduction to the usage of @Transactional in Spring
Introduction: @Transactional provides a quick way to control transaction management in spring, but many people simply use @Transactional and do not have an in-depth understanding of how to use each configuration item. This article will explain the use of each configuration item in depth. .
1. Definition of @Transactional
@Transactional in Spring is based on the dynamic proxy mechanism, which provides a transparent transaction management mechanism to facilitate and quickly solve the problem of development problems encountered. In reality, actual problems are often much more complex than we expected, which requires an in-depth understanding of @Transactional in order to deal with complex problems.
First let’s take a look at the code definition of @Transactional:
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface Transactional { /** * A qualifier value for the specified transaction. * <p>May be used to determine the target transaction manager, * matching the qualifier value (or the bean name) of a specific * {@link org.springframework.transaction.PlatformTransactionManager} * bean definition. */ String value() default ""; /** * The transaction propagation type. * Defaults to {@link Propagation#REQUIRED}. * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior() */ Propagation propagation() default Propagation.REQUIRED; /** * The transaction isolation level. * Defaults to {@link Isolation#DEFAULT}. * @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel() */ Isolation isolation() default Isolation.DEFAULT; /** * The timeout for this transaction. * Defaults to the default timeout of the underlying transaction system. * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout() */ int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; /** * {@code true} if the transaction is read-only. * Defaults to {@code false}. * <p>This just serves as a hint for the actual transaction subsystem; * it will <i>not necessarily</i> cause failure of write access attempts. * A transaction manager which cannot interpret the read-only hint will * <i>not</i> throw an exception when asked for a read-only transaction. * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly() */ boolean readOnly() default false; /** * Defines zero (0) or more exception {@link Class classes}, which must be a * subclass of {@link Throwable}, indicating which exception types must cause * a transaction rollback. * <p>This is the preferred way to construct a rollback rule, matching the * exception class and subclasses. * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)} */ Class<? extends Throwable>[] rollbackFor() default {}; /** * Defines zero (0) or more exception names (for exceptions which must be a * subclass of {@link Throwable}), indicating which exception types must cause * a transaction rollback. * <p>This can be a substring, with no wildcard support at present. * A value of "ServletException" would match * {@link javax.servlet.ServletException} and subclasses, for example. * <p><b>NB: </b>Consider carefully how specific the pattern is, and whether * to include package information (which isn't mandatory). For example, * "Exception" will match nearly anything, and will probably hide other rules. * "java.lang.Exception" would be correct if "Exception" was meant to define * a rule for all checked exceptions. With more unusual {@link Exception} * names such as "BaseBusinessException" there is no need to use a FQN. * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)} */ String[] rollbackForClassName() default {}; /** * Defines zero (0) or more exception {@link Class Classes}, which must be a * subclass of {@link Throwable}, indicating which exception types must <b>not</b> * cause a transaction rollback. * <p>This is the preferred way to construct a rollback rule, matching the * exception class and subclasses. * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)} */ Class<? extends Throwable>[] noRollbackFor() default {}; /** * Defines zero (0) or more exception names (for exceptions which must be a * subclass of {@link Throwable}) indicating which exception types must <b>not</b> * cause a transaction rollback. * <p>See the description of {@link #rollbackForClassName()} for more info on how * the specified names are treated. * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)} */ String[] noRollbackForClassName() default {}; }
Based on the source code, we can find that in @Transactional, it turns out that there is this Multiple attributes can be configured to achieve complex application control. The specific usage and function of each attribute will be explained and explained one by one later in this article.
2. Spring configuration using @Transactional
In order to use transaction management based on @Transactional, the following configuration needs to be done in Spring:
<beans:bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <beans:property name="dataSource" ref="dataSource" /> <beans:property name="entityManagerFactory" ref="entityManagerFactory" /> </beans:bean> <!-- 声明使用注解式事务 --> <tx:annotation-driven transaction-manager="transactionManager" />
DataSource is the object instance of the data source defined in the Spring configuration file. EntityManagerFactory is an entity class manager based on JPA: org.springframework.orm.jpa. LocalContainerEntityManagerFactoryBean. These are used to configure the connection information with the database. In essence, @Transactional uses JDBC transactions for transaction control.
The declaration of the
3. @Transactional value
value here is mainly used to specify different transaction managers; mainly used to satisfy the need for different transactions in the same system Manager. For example, in Spring, two transaction managers, txManager1 and txManager2, are declared.
Then, users can use this parameter to specify a specific txManager as needed.
Some students will ask what is going on What if there are multiple transaction managers? For example, in a system that needs to access multiple data sources or multiple databases, multiple transaction managers will inevitably be configured.
4. @Transactional propagation
Propagation supports 7 different propagation mechanisms:
REQUIRED
Business methods need to run in a transaction. If the method is already in a transaction when running, then join the transaction, otherwise create a new transaction yourself. This is spring's default propagation behavior.
SUPPORTS:
If the business method is called within a transaction scope, the method becomes part of the transaction. If the business method is called within the scope of a transaction, the method becomes part of the transaction. If called outside the transaction scope, the method is executed in an environment without a transaction.
MANDATORY:
It can only be executed in an existing transaction. The business method cannot initiate its own transaction. If the business method does not have a transaction, When called in an environment, an exception will be thrown
REQUIRES_NEW
The business method will always initiate a new transaction for itself. If the method is already running In a transaction, the original transaction is suspended and a new transaction is created. The new transaction will not end until the method ends, and the original transaction will resume execution.
NOT_SUPPORTED
Declaring a method requires a transaction. If the method is not associated with a transaction, the container will not open a transaction for it. If the method is called in a transaction, the transaction will be suspended. After the call is completed, the original transaction will resume execution.
NEVER:
The declared method must not be executed within the transaction scope. If the method When executed within a certain transaction scope, the container will throw an exception. Only when it is not associated with a transaction, it will execute normally.
NESTED:
如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.
其实大家最感到困惑的是REQUIRED_NEW和NESTED两种不同的传播机制,功能类似,都涉及到了事务嵌套的问题,那两者有何区别呢?该如何正确使用这两种模式呢?
以下是摘自Spring的文档:
PROPAGATION_REQUIRES_NEW : uses a completely independent transaction for each affected transaction scope. In that case, the underlying physical transactions are different and hence can commit or roll back independently, with an outer transaction not affected by an inner transaction's rollback status.
内部的事务独立运行,在各自的作用域中,可以独立的回滚或者提交;而外部的事务将不受内部事务的回滚状态影响。
ROPAGATION_NESTED : uses a single physical transaction with multiple savepoints that it can roll back to. Such partial rollbacks allow an inner transaction scope to trigger a rollback for its scope, with the outer transaction being able to continue the physical transaction despite some operations having been rolled back. This setting is typically mapped onto JDBC savepoints, so will only work with JDBC resource transactions.
NESTED的事务,基于单一的事务来管理,提供了多个保存点。这种多个保存点的机制允许内部事务的变更触发外部事务的回滚。而外部事务在混滚之后,仍能继续进行事务处理,即使部分操作已经被混滚。 由于这个设置基于JDBC的保存点,所以只能工作在JDBC的机制智商。
由此可知, 两者都是事务嵌套,不同之处在于,内外事务之间是否存在彼此之间的影响;NESTED之间会受到影响,而产生部分回滚,而REQUIRED_NEW则是独立的。
以上就是Spring中@Transactional用法详细介绍的内容,更多相关内容请关注PHP中文网(www.php.cn)!