background
As a back-end development, @Transactional has been used all the time, but we always encounter all kinds of bizarre situations that do not take effect, and every time we check information everywhere to solve it. I just want to write an article to sort it out. I don’t need to look around when I encounter it later, and I will add it if there are new situations.
@Transactional
Declarative transaction
spring support programmatic transaction and declarative transaction two kinds. Programmatic transaction is to use code to manually control the start, commit or rollback of the transaction, so that the business code becomes impure, the function code and the auxiliary code are mixed together, and there will be many duplicate codes. So we generally use declarative transactions. There are generally two ways of declarative transaction, one is based on the xml configuration file of tx and aop namespace, and the other is to use @Transactional annotation. The most widely used one is the @Transactional annotation.
Attributes
Attributes | Types of | description |
---|---|---|
value、transactionManager | String | Optional qualified descriptor, specifying the transaction manager used |
propagation | enum: Propagation | Optional transaction propagation behavior settings |
isolation | enum: Isolation | Optional transaction isolation level settings |
readOnly | boolean | "Read and write" or "read only" transaction, the default is false |
timeout | int (in seconds granularity) | Transaction timeout setting, default -1 |
rollbackFor | Array of Class objects, must inherit from Throwable | Array of exception classes that caused the transaction to roll back |
rollbackForClassName | Array of class names, must inherit from Throwable | Array of exception class names that caused the transaction to roll back |
noRollbackFor | Array of Class objects, must inherit from Throwable | An array of exception classes that will not cause the transaction to roll back |
noRollbackForClassName | Array of class names, must inherit from Throwable | Array of exception class names that will not cause the transaction to roll back |
value、transactionManager
Specify the name of the transaction manager, which is generally used in the transaction processing of multi-data source applications to clearly specify which data source to use for transaction management
Propagation: transaction propagation behavior [ write demo code after todo and run verification ]
- Propagation.REQUIRED
- If there is currently a transaction, then join the transaction; if there is no current transaction, then create a new transaction. It's the default value.
- [The outer transaction and the inner transaction are one transaction, to be submitted together to commit, to be rolled back and rolled back together]
- Propagation.SUPPORTS
- If there is currently a transaction, then join the transaction; if there is no current transaction, continue to run in a non-transactional manner.
- [If there is an outer transaction, it is the same as Propagation.REQUIRED. If there is no outer transaction, run in a non-transactional manner]
- Propagation.MANDATORY
- If there is currently a transaction, then join the transaction; if there is no current transaction, an exception is thrown .
- [If there is an outer transaction, it is the same as Propagation.REQUIRED. If there is no outer transaction, throw an exception]
- Propagation.REQUIRES_NEW
- Create a new transaction, if there is a transaction currently, then suspend the current transaction.
- [The outer transaction is rolled back, and the internal transaction is submitted normally; the internal transaction is rolled back, and if the external transaction captures the exception and does not throw it up, the external transaction continues to execute]
- Propagation.NOT_SUPPORTED
- Run in non-transactional mode. If there is a transaction currently, the current transaction is suspended.
- [The outer layer does not affect the affairs, the inner layer runs in a non-transactional way]
- Propagation.NEVER
- Run in non-transactional mode. If there is a transaction currently, an exception is thrown.
- Propagation.NESTED
- If there is currently a transaction, create a transaction to run as a nested transaction of the current transaction; if there is no current transaction, the value is equivalent to Propagation.REQUIRED.
- [External affairs roll back, internal affairs will definitely roll back; internal affairs roll back, external affairs continue to execute]
Propagation.REQUIRES_NEW、Propagation.NESTED、Propagation.REQUIRED 对比 Define serviceA.methodA() to be modified by Propagation.REQUIRED; |
|||
Abnormal state | Propagation.REQUIRES_NEW (two independent transactions) |
Propagation.NESTED (B's transaction is nested in A's transaction) |
Propagation.REQUIRED (same transaction) |
methodA throws an exception and methodB is normal |
A rolls back, B submits normally | A and B roll back together | A and B roll back together |
methodA is normal and methodB throws an exception |
1. If the exception of B is caught in A, and the exception is not continued to be thrown upwards, B will roll back first, and then A will submit normally; 2. If A does not catch the exception of B, the default will be the exception of B will be thrown upwards, then B Roll back first, then roll back A |
B rolls back first, and A submits normally | A and B roll back together |
methodA throws an exception methodB throws an exception |
B rolls back first, A rolls back again | A and B roll back together | A and B roll back together |
methodA is normal methodB is normal |
B submits first, A then submits | A and B are submitted together | A and B are submitted together |
isolation: transaction isolation level
It has the same meaning as the transaction isolation level of the database, except that there is more default. The difference is that isolation specifies the transaction isolation level of the current connection session, while the database refers to the global transaction isolation level of the current database. When the two are not the same, the isolation level of the current session shall prevail.
- Isolation.DEFAULT
- Use the database default transaction isolation level
- Isolation.READ_UNCOMMITTED
- Read uncommitted
- Isolation.READ_COMMITTED
- Read submitted
- Isolation.REPEATABLE_READ
- Repeatable
- Isolation.SERIALIZABLE
- Serialization
readOnly
- Set whether the current transaction is a read-only transaction, set to true to indicate read-only, false to indicate read-write, the default value is false
- What happens if you set it to true but perform a write operation? Write demo later and run
timeout
- Set the timeout in seconds for the transaction. The default value is -1, which means it will never time out. Overtime transactions will be rolled back.
rollbackFor
- This property is used to set the array of exception classes that need to be rolled back. When an exception in the specified exception array is thrown in the method, the transaction is rolled back. E.g:
- Specify a single exception class: @Transactional(rollbackFor=RuntimeException.class)
- Specify multiple exception classes: @Transactional(rollbackFor={RuntimeException.class, Exception.class})
rollbackForClassName
- This property is used to set the array of exception class names that need to be rolled back. When an exception in the specified exception name array is thrown in the method, the transaction is rolled back.
- Specify a single exception class name: @Transactional(rollbackForClassName="RuntimeException")
- Specify multiple exception class names: @Transactional(rollbackForClassName={"RuntimeException","Exception"})
noRollbackFor
-
This property is used to set the exception class array that does not need to be rolled back. When an exception in the specified exception array is thrown in the method, the transaction will not be rolled back.
-
Specify a single exception class: @Transactional(noRollbackFor=RuntimeException.class)
-
Specify multiple exception classes: @Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassName
- This property is used to set an array of exception class names that do not need to be rolled back. When an exception in the specified exception name array is thrown in the method, the transaction will not be rolled back.
- Specify a single exception class name: @Transactional(noRollbackForClassName="RuntimeException")
- Specify multiple exception class names: @Transactional(noRollbackForClassName={"RuntimeException","Exception"})
use
- @Transactional should be decorated in the interface implementation class or interface implementation method, not in the interface class
- The annotation attribute on the method will override the same attribute on the class annotation
- The @Transactional declared by the parent class will perform transaction enhancement on all methods of the subclass; the subclass override overrides the parent class to override the declaration configuration in @Transactional
- Only method calls from outside will be captured by the AOP proxy, that is, internal methods of the class calling other methods of this class will not cause transactional behavior, even if the called method is decorated with @Transactional annotation
- @Transactional modifies the public method to work
- If the exception (runtime exception) in the interface is caught but not thrown, the transaction will not be rolled back
principle
[I don’t deserve todo, I'll learn it after using it]
reference
Thoroughly grasp the use of @transactional in Spring
Detailed explanation of @Transactional(rollbackFor = Exception.class) attribute in Spring
Understanding of PROPAGATION_NESTED
What to do if the Spring transaction isolation level is different from the level set by MySQL
Spring uses annotations for transaction management
@Transactional Set nested transactions not to roll back
Understanding of Spring transactions (Controller can use @Transactional)
The spring boot @Transactional annotation transaction does not roll back and does not work, invalid
SpringBoot service transaction annotation @Transactional does not work
Catch exceptions and rollback solutions in SpringBoot @Transactional
Declarative transactions do not rollback @Transactional's avoidance of pitfalls is used correctly
Use @Transactional annotation to configure transaction management in Spring Boot
Spring @Transactional annotation does not roll back and does not work and is invalid