引言: 在Spring中@Transactional提供一种控制事务管理的快捷手段,但是很多人都只是@Transactional简单使用,并未深入了解,其各个配置项的使用方法,本文将深入讲解各个配置项的使用。
1. @Transactional的定义
Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题。在现实中,实际的问题往往比我们预期的要复杂很多,这就要求对@Transactional有深入的了解,以来应对复杂问题。
首先我们来看看@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 {};
- }
2. 使用@Transactional的Spring配置
为了使用基于@Transactional的事务管理,需要在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" />
<annotation-driven>标签的声明,则是在Spring内部启用@Transactional来进行事务管理,类似开关之类的声明。
3. @Transactional之value
value这里主要用来指定不同的事务管理器;主要用来满足在同一个系统中,存在不同的事务管理器。比如在Spring中,声明了两种事务管理器txManager1, txManager2.
然后,用户可以根据这个参数来根据需要指定特定的txManager.
那有同学会问什么情况下会存在多个事务管理器的情况呢? 比如在一个系统中,需要访问多个数据源或者多个数据库,则必然会配置多个事务管理器的。
4. @Transactional之propagation
Propagation支持7种不同的传播机制:
- REQUIRED
- SUPPORTS:
- MANDATORY:
- REQUIRES_NEW
- NOT_SUPPORTED
- NEVER:
- NESTED:
如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.
其实大家最感到困惑的是REQUIRED_NEW和NESTED两种不同的传播机制,功能类似,都涉及到了事务嵌套的问题,那两者有何区别呢?该如何正确使用这两种模式呢?