There are some points to pay attention to when using @ Transactional:
- Spring will roll back (RuntimeException) and its subclasses by default. When an Exception and its subclasses are encountered, it will not roll back
- @Transactional annotations should only be applied to public methods, which is determined by the nature of Spring AOP
@For the Transactional annotation to take effect, you need to configure @ EnableTransactionManagement, but if you use SpringBoot, you don't need it:
@SpringBootApplication @EnableTransactionManagement // In fact, this line of annotation is unnecessary. It is already provided in the TransactionAutoConfiguration automatic configuration class public class SpringTransactionalApplication { public static void main(String[] args) { SpringApplication.run(SpringTransactionalApplication.class, args); } }
TransactionAutoConfiguration autoconfiguration class defines many bean s related to transaction processing, among which TransactionInterceptor is closely related to @ Transactional annotation
Each method annotated with @ Transactional will create a facet. All transaction processing logic is completed by this facet. The specific implementation of this facet is the TransactionInterceptor class
Note that this TransactionInterceptor is a singleton object, and all methods with @ Transactional annotation will be represented by this object:
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { // ...... @Override @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // Work out the target class: may be {@code null}. // The TransactionAttributeSource should be passed the target class // as well as the method, which may be from an interface. Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // Adapt to TransactionAspectSupport's invokeWithinTransaction... return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed); } // ...... } public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean { @Nullable protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // ...... // Here, the TransactionAttributeSource object saves the @ Transactional annotation attribute information on all methods in the application, which is saved by Map, where // key consists of target method object + target class targetClass object, so the @ Transactional annotation attribute information on the target method can be uniquely found through method+targetClass TransactionAttributeSource tas = getTransactionAttributeSource(); // This TransactionAttribute object saves all attribute configurations of the target method @ Transactional annotation, such as timeout,propagation,readOnly, and so on, // Subsequently, these attributes are used to complete the corresponding operations final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // ...... TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification); Object retVal; try { // This will eventually call the target method retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // The target method throws an exception, and determines whether to roll back the transaction according to the @ Transactional annotation attribute configuration completeTransactionAfterThrowing(txInfo, ex); throw ex; } // ...... // The target method is executed normally, and the transaction is committed commitTransactionAfterReturning(txInfo); return retVal; } }
@Meaning of Transactional annotation attribute:
- value: an optional qualified descriptor that specifies the transaction manager to use
- Propagation: optional transaction propagation behavior settings
- Isolation: optional transaction isolation level setting
- readOnly: read / write or read-only transaction. The default is read / write
- Timeout: transaction timeout setting
- rollbackFor: array of exception classes that cause transaction rollback
- rollbackForClassName: array of exception class names that cause transaction rollback
- oRollbackFor: array of exception classes that will not cause transaction rollback
- noRollbackForClassName: array of exception class names that will not cause transaction rollback
Meanings of attribute values of propagation:
- Propagation.REQUIRED: if there is a transaction, join the transaction. If not, create a new one
- Propagation.NOT_SUPPORTED: this method does not open transactions
- Propagation.REQUIREDS_NEW: create a new transaction no matter whether there is a transaction or not. The original transaction is suspended. After the new transaction is completed, continue to execute the old transaction
- Propagation.MANDATORY: it must be executed in an existing transaction, or an exception will be thrown
- Propagation.NEVER: it cannot be executed in a transaction, that is, there must be no transaction at present, otherwise an exception will be thrown
- Propagation.SUPPORTS: if a transaction currently exists, it will run in the transaction Otherwise, it runs as a non transaction
- Propagation.NESTED: if there is a transaction currently, it will run in a nested transaction. If there is no transaction currently, it will be executed according to the REQUIRED attribute It works only with the DataSourceTransactionManager transaction manager
See the getTransaction method of AbstractPlatformTransactionManager class for how Spring handles this attribute
Meaning of attribute values of isolation:
- TransactionDefinition.ISOLATION_DEFAULT: This is the default value, indicating that the default isolation level of the underlying database is used
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED: this isolation level indicates that one transaction can read data modified by another transaction but not yet committed This level does not prevent dirty reads, non repeatable reads and unreal reads, so it is rarely used For example, PostreSQL does not actually have this level
- TransactionDefinition.ISOLATION_READ_COMMITTED: this isolation level indicates that one transaction can only read the committed data of another transaction This level can prevent dirty reading, which is also the recommended value in most cases
- TransactionDefinition.ISOLATION_REPEATABLE_READ: this isolation level indicates that a transaction can repeatedly execute a query in the whole process, and the records returned each time are the same This level prevents dirty reads and non repeatable reads
- TransactionDefinition.ISOLATION_SERIALIZABLE: all transactions are executed one by one, so that there is no interference between transactions. In other words, this level can prevent dirty reading, non repeatable reading and phantom reading However, this will seriously affect the performance of the program, and this level is not usually used