This is the 11th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021

preface

A transaction is one or more database operations that require atomicity, isolation, consistency, and persistence at the same time, but at some point there can be transaction failures that, if you don’t pay attention, can suddenly backfire on you.

For an introduction to transactions, see the SpringBoot foundation for declarative and faceted and programmatic transactions, which covers the four main characteristics of a transaction, its isolation level, Transactional propagation behavior, and @Transactional parameter interpretation

Transaction does not take effect scenario

The proper use of a transaction depends on the transaction being configured and used correctly; if it is used incorrectly, the transaction will not take effect

The database engine does not support transactions

For MySQL, only InnoDB and NDB engines currently support transactions, among which the more common MyISAM does not support transactions.

If you use an engine that does not support transactions, transactions do not take effect.(THIS problem occurred in my tests while writing this article 😂)

The method usesfinalorstaticmodified

When final or static is used, it cannot be overridden by the proxy class, so the transaction is lost.

IDEA will prompt an error, so IDEA is rare, the error is as follows

Reports the cases when your code prevents a class from being subclassed by some framework (e.g. Spring or Hibernate) at runtime.
Copy the code

nonpublicMethod of decoration

Specific reason why call AbstractFallbackTransactionAttributeSource computeTransactionAttribute method can judge, whether the method is public methods.

IDEA will prompt an error, so IDEA is rare, the error is as follows

Reports the cases when your code prevents a class from being subclassed by some framework (e.g. Spring or Hibernate) at runtime.
Copy the code

Non-transactional methods internally call transactional methods in the same class

A transaction is invalidated when A method without A transaction calls B with A transaction using this

@Override
public void A() {
    this.B();
}

@Override
@Transactional
 public void B() {
    mapper.saveStudent(new Student("A"));
    int zdc = 8/0;
}
Copy the code

A call to method B will roll back normally, but A call to method B will not roll back.

Rollback failed or rollback scenario prevented

Why a transaction rolls back, and under what circumstances, requires parameters to be bounded. Most of these parameters are in @Transactional.

Focus on the @Transactional argument here

parameter role
The value or transactionManager You can use this property to specify which transaction manager to select when multiple transaction managers are configured.
propagation Propagation. The default value is Propagation.REQUIREDClick on the
isolation The Isolation level of the transaction. The DEFAULT value is isolation.default for more detailsClick on the
timeout The timeout period for a transaction. The default value is -1. If the timeout limit is exceeded but the transaction has not completed, the transaction is automatically rolled back.
readOnly Specifies whether the transaction is read-only. The default value is false. To ignore methods that do not require a transaction, such as reading data, you can setread-onlyTo true.
RollbackFor or rollbackForClassName Used to specify the type of exception that can trigger transaction rollback. Multiple exception types can be specified.
NoRollbackFor or noRollbackForClassName Throws the specified exception type, without rolling back the transaction, or you can specify multiple exception types.

manualtry-catchThe abnormal

For a Spring transaction to be rolled back, it must throw an exception that can be caught. If the exception is try-caught, the program considers that no exception was thrown and does not roll back

@Override @Transactional public void B() { try{ mapper.saveStudent(new Student("A")); int zdc = 8/0; }catch (Exception e){ e.printStackTrace(); }} // Will not be rolled backCopy the code

The exception thrown does not belong toRuntimeExceptionorErrorabnormal

This is commented out in the @Transactional rollbackFor parameter in the JDK

By default, a transaction will be rolling back on {@link RuntimeException} and {@link Error} but not on checked exceptions (business  exceptions). See {@link org.springframework.transaction.interceptor. DefaultTransactionAttribute#rollbackOn(Throwable)}  for a detailed explanation.Copy the code

By default, only RuntimeExceptions or Errors are handled. If you throw other exceptions, they are not handled

@Override @Transactional public void B() throws NotFoundException { mapper.saveStudent(new Student("A")); throw new NotFoundException("zdc"); } // No rollbackCopy the code

So to pass all exceptions, we usually define rollbackFor = exception. class on @Transactional to catch all exceptions. Of course, you can also assign Exception. Class to Throwable. Class

@Override @Transactional(rollbackFor = Exception.class) public void B() throws NotFoundException { mapper.saveStudent(new Student("A")); throw new NotFoundException("zdc"); } // will roll backCopy the code

noRollbackForDefine the error

NoRollbackFor in @Transactional throws the specified exception type. The transaction is not rolled back. If a throw exception is incorrectly set, the transaction is not rolled back

@Override @Transactional(noRollbackFor = Exception.class) public void B() throws NotFoundException { mapper.saveStudent(new Student("A")); int zdc = 1/0; } // No rollbackCopy the code

Bad propagation property or bad nesting

Propagation behavior of transactions. Default value is Propagation.REQUIRED

In this section, examples of B primary method, C submethod, whether there is a transaction for operation B, and propagation property for operation C are given. There are too many cases in this section, which are directly explained in the following table in the explanation part of this paper

@Service @Slf4j public class Transaction3ServiceImpl implements Transaction3Service { @Autowired private Transaction4Service transaction4Service; @Autowired(required = false) private StudentMapper mapper; Public void B(){mapper.saveStudent(new); public void B(){mapper.saveStudent(new) Student("ZZZDC")); transaction4Service.C(); // int zdc = 1/0; }}Copy the code
@Service @Slf4j public class Transaction4ServiceImpl implements Transaction4Service { @Autowired(required = false) private StudentMapper mapper; Public void C() {mapper.saveStudent(new); public void C() {mapper.saveStudent(new) Student("ZDDDC")); //int zdc = 1/0; If an exception occurs, use this instead of}}Copy the code
Propagation behavior Explanations in this article
REQUIRED If B has a transaction, C joins the transaction(If an exception occurs, the BC is rolled back together); If B does not have a transaction, C creates a new transaction(B does not roll back, and only part of C will be rolled back if C is abnormal)
SUPPORTS If B has a transaction, C joins the transaction(If an exception occurs, the BC is rolled back together); If B does not have a transaction, C continues to run in a non-transactional manner(BC does not roll back in any case)
MANDATORY If B has a transaction, C joins the transaction(Roll back all together if an exception occurs); If B has no transaction, C throws an exception.(C) no transaction B)
REQUIRES_NEW If B does not have a transaction,C creates a new transaction(If transaction B is abnormal, it will not be rolled back. If transaction C is abnormal, C will be rolled back.); If B has a transaction,C suspends B’s transaction and creates a new one(This is two transactions, part of their own exception, part of their own rollback)
NOT_SUPPORTED If B does not have a transaction,C runs in a non-transactional manner(No rollback in any case); If B has a transaction,C suspends the current transaction and runs in a non-transactional manner(If part B fails, part B will be rolled back and part C will not be rolled back. Non-transaction C part error, no rollback)
NEVER If B does not have a transaction,C runs in a non-transactional manner(No rollback in any case)If B has a transaction,C throws an exception(C error,B rollback due to exception)
NESTED The same effect as REQUIRED.

In this place, the propagation behavior of the transaction will affect the state of the transaction. In the case of nested transactions, if a part of the transaction fails to roll back, it may be all or part of the rollback depending on the situation.

If propagation behavior parameters are used, they need to be carefully analyzed, tested, and delivered

The SpringBoot scenario

The transaction manager is not configured or incorrectly configured

The old SSM project configuration is incorrect

SpringMVC scan error

The old SSM project configuration is incorrect

Not managed by Spring

Special case special analysis

Source: author: ZOUZDC links: https://juejin.cn/post/7028963866063306760 re the nuggets copyright owned by the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.Copy the code