1. Transaction isolation level
In Springboot application, if we want to implement that if an exception occurs when the method is executed, it will trigger transaction rollback. You can add it to the method@Transactionalannotation. If the application uses mysql database, although mysql itself also has a transaction isolation mechanism, in Spring+ database applications, Spring transactions will be the basis. The transaction isolation level defined by mysql is reproducible. When using a combination of Spring Boot and MySQL, if you do not specify the isolation level specifically, the actual use of MySQL will be the default value of REPEATABLE READ. If you do not want to use repeatable reads in some specific scenarios, you can specify it through the isolation property of the @Transactional annotation. The options supported by isolation are:
- ISOLATION_DEFAULT: Use the default isolation level of the backend database.
- ISOLATION_READ_UNCOMMITTED: The lowest isolation level allows reading of uncommitted data changes, which may result in dirty reads, non-repeatable reads, or phantom reads.
- ISOLATION_READ_COMMITTED: Allows reading of submitted data, prevents dirty reading, but may not be repeated or phantom reading.
- ISOLATION_REPEATABLE_READ: The multiple reads to the same field are consistent, unless the data is modified by the current transaction itself, which can prevent dirty reads and non-repeatable reads, but phantom reads may still occur.
- ISOLATION_SERIALIZABLE: The highest isolation level, completely obeying the isolation level of ACID, and all transactions are executed one by one in sequence, which can prevent dirty reading, non-repeatable reading and phantom reading.
Example of usage:
@Transactional(isolation = Isolation.READ_COMMITTED) public void performTransaction() { // Business logic code}
2. Transmission behavior of transactions
The propagation behavior of a transaction refers to how the transactions between the two should be related when one transaction method is called by another transaction method.By configuring different propagation behaviors, you can control whether new transactions should be created, existing transactions should be joined, or executed in a non-transactional manner, etc.
Spring provides seven standard transaction propagation behaviors that can be specified by the propagation attribute of the @Transactional annotation. Here are detailed descriptions of these transmission behaviors:
PROPAGATION_REQUIRED (default):
If a transaction currently exists, join the transaction; if it does not exist, create a new transaction.
This is the most commonly used communication behavior and is suitable for most scenarios.
PROPAGATION_SUPPORTS
If a transaction currently exists, join the transaction; if it does not exist, execute in a non-transactional manner.
Suitable for operations that do not have special requirements for transactionality, such as query operations.
PROPAGATION_MANDATORY:
If a transaction currently exists, join the transaction; if it does not exist, an exception is thrown (IllegalTransactionStateException).
Method used to force execution in existing transactions.
PROPAGATION_REQUIRES_NEW:
Create a new transaction, and if the transaction currently exists, the current transaction will be suspended.
Applicable to business logic that needs to be executed independently of external transactions, ensuring that internal operations do not affect the results of external transactions.
PROPAGATION_NOT_SUPPORTED:
Execute operations in a non-transactional manner, and if a transaction currently exists, the current transaction is suspended.
Suitable for operations that clearly do not require transactions, such as reading system configuration or sending emails.
PROPAGATION_NEVER:
Execute in a non-transactional manner. If a transaction currently exists, an exception is thrown (IllegalTransactionStateException).
Method used to strictly prohibit execution in a transaction environment.
PROPAGATION_NESTED:
If a transaction currently exists, it is executed within a nested transaction; if it does not exist, a new transaction is created.
Nested transactions are part of external transactions, but can be committed or rolled back independently of external transactions. This propagation behavior relies on the support of the underlying database and drivers, such as MySQL's InnoDB engine supports savepoints (SAVEPOINT), enabling nested transactions.
Things to note
Performance considerations: Choosing the right propagation behavior is very important for performance optimization. For example, both PROPAGATION_REQUIRES_NEW and PROPAGATION_NOT_SUPPORTED involve transaction suspension and recovery, which may result in additional overhead.
Transaction boundaries: Correct understanding of transaction boundaries and the impact of propagation behavior can help avoid potential problems such as deadlocks, data inconsistencies, etc.
Nested Transaction Support: Not all databases support nested transactions. When using PROPAGATION_NESTED, make sure your database and drivers support this feature.
Selecting appropriate propagation behaviors based on the specific needs of the application can help you better manage transactions and ensure data consistency and integrity.
3. The pitfalls in Spring transactions
In the same class, write two methods and internal calls will cause the transaction settings to be invalid. The reason is that it is not useful
For proxy objects. Specifically:
Spring uses AOP to implement transaction management, which creates a proxy object for each method with @Transactional annotation. When you get an instance of this class through the Spring container and call its methods, you actually call the method of the proxy object, not the method of the original class. The proxy object is responsible for inserting transaction management logic before and after method calls.
However, when you directly call another @Transactional method in a non-static method of one class, the call does not go through the proxy object, but directly calls the original class's methods. Therefore, transaction management logic will not be applied, resulting in transaction settings invalidation.
Method 1:
1) Import spring-boot-starter-aop dependencies
2) Add annotation to the startup class @EnableAspectJAutoProxy(exposeProxy=true)
3) Use () to call the method in the place where the transaction is used.
Example of usage:
import ; @Service public class MyService { @Transactional public void transactionalMethod() { // Transaction logic } public void performOperation() { // Business logic ((MyService) ()).transactionalMethod(); } }
However, this method makes the code more complex and unintuitive, so try to avoid using it unless absolutely necessary.
The most recommended approach is to move transaction methods to different classes. This ensures that each time the transaction method is called, it is performed through the proxy object, thus ensuring that transaction management takes effect. For details, please refer to Method 2:
Method 2:
@Service public class MyService { @Autowired private AnotherService anotherService; public void performOperation() { // Business logic (); } } @Service public class AnotherService { @Transactional public void transactionalMethod() { // Transaction logic } }
Expand: @Transactional supports configuration properties large-scale point
In addition to the propagation and isolation mentioned above, the @Transactional annotation also supports the configuration of the following properties:
1. value or transactionManager
- effect: Specify the name of the transaction manager to use. If you have multiple transaction managers in your application (for example, for different data sources), you can use this property to specify which transaction manager should manage the transactions of the current method.
-
default value:
"transactionManager"
, which is the default transaction manager bean name for Spring.
@Transactional("myTransactionManager") public void myTransactionalMethod() { // Business logic }
2. readOnly function:
Specifies whether a transaction is a read-only transaction. Read-only transactions are often used for query operations that can improve performance (e.g., disable dirty page writing, etc.).
Get the value:
-
false
(Default): Transactions are not read-only, and insert, update and delete operations are allowed. -
true
: Transactions are read-only and only query operations are allowed.
@Transactional(readOnly = true) public List<Entity> findAllEntities() { // Query operation }
3. timeout
Function: Define the timeout time (in seconds) of the transaction. If the transaction fails to complete within the specified time, Spring will automatically roll back the transaction.
Default value: -1, indicating the default timeout setting used for backend database or transaction manager.
@Transactional(timeout = 30) public void longRunningOperation() { // Long-running business logic }
4. rollbackFor
Function: Specify which exceptions should trigger transaction rollback. By default, only unchecked exceptions (such as RuntimeException and its subclasses) trigger rollback. You can specify that other exception types should also trigger rollback through this property.
Value: One or more exception classes, which can be separated by commas.
@Transactional(rollbackFor = {, }) public void methodThatMayThrowExceptions() { // Business logic }
5. noRollbackFor
Function: Specify which exceptions should not trigger transaction rollback. By default, all unchecked exceptions will trigger rollbacks, but you can specify that some exceptions should not trigger rollbacks through this property.
Value: One or more exception classes, which can be separated by commas.
@Transactional(noRollbackFor = ) public void methodThatMayThrowCustomException() { // Business logic }
6. validation
Function: Specifies whether to verify transaction properties before the transaction begins. If set to true, Spring checks whether the transaction properties meet the requirements before the transaction starts, and throws an exception if they do not.
Default value: false, that is, no verification is performed.
@Transactional(validation = true) public void validateTransactionalAttributes() { // Business logic }
This is the article about several issues that need to be paid attention to when using Springboot @Transactional. For more related content on using Springboot @Transactional, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!