Biography: Swing unruly, love life. Java Cultivator (wechat official ID: Java Cultivator), welcome to follow. Access to 2000G of detailed information on the 2020 interview questionsCopy the code
This paper has two objectives:
1. When using Spring transactions, what situations will cause transactions to fail?
2. What are some ways to quickly locate transaction related bugs?
3. Welfare at the end of the article
1. 7 cases of transaction failure
-
Spring transaction management is not enabled
-
Methods are not of type public
-
The transaction manager is not configured for the data source
-
Self call problem
-
Exception type error
-
The abnormality was swallowed
-
The business and Spring transaction code must be in the same thread
1.1. Spring transaction management is not enabled
@ EnableTransactionManagement annotation is used to enable the function of the spring automatic management affairs, this annotation don’t forget to write.
1.2. Methods are not public
@Transaction can be used on classes, interfaces, and public methods. If @TrasAction is used on non-public methods, the Transaction will not be valid.
1.3 The data source is not configured with a transaction manager
Spring uses a transaction manager to manage transactions. Do not forget to configure the transaction manager. Note that one transaction manager is configured for each data source:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource)
{
return new DataSourceTransactionManager(dataSource);
}
Copy the code
1.4. Self call problem
Spring uses AOP to generate a proxy object for the bean that requires Spring to manage transactions, and then intercepts the execution of the target method through the proxy object. Transaction functionality is added before and after the method, so the transaction will only take effect when the target method is called through the proxy object.
Consider the following code: when an external call to M1 is made directly, does the m2 transaction take effect?
@Component public class UserService { public void m1(){ this.m2(); } @transactional public void m2(){}Copy the code
This is not a proxy object. This.m2 () is not used by the transaction interceptor, so the transaction is invalid. If an external direct call is made to the m2 method through the UserService bean, the transaction is valid. The above code can be adjusted as follows: @1 injects itself into UserService, and the M2 transaction in M1 takes effect
@Component public class UserService { @Autowired //@1 private UserService userService; public void m1() { this.userService.m2(); } @transactional public void m2() {}Copy the code
Important: The transaction must be accessed through the proxy object method for it to take effect.
1.5. The exception type is incorrect
Spring uses a try catch on a business method to roll back a transaction. When a specified exception is caught, spring rolls back a transaction.
Spring does not roll back a transaction for any exception, but by default for RuntimeException and Error cases.
You can also customize the exception type for rollback:
Transactional(rollbackFor = {list of exception types})Copy the code
1.6. Abnormality is swallowed
When a business method throws an exception and Spring senses it, the transaction will roll back. If the exception is swallowed internally, the transaction will not feel the exception and the transaction will not roll back.
As shown in the following code, transaction operation 2 has an exception but is caught and the transaction will not be rolled back
@Transactional public void m1(){Transactional public void m1(){Transactional public void m1(){Transactional public void m1(){Transactional public void m1(){Transactional public void m1(){Copy the code
1.7. Business and Spring transaction code must be in one thread
Spring transaction implementation uses ThreadLocal, which can be used to share data in the same thread. Data can only be shared when the same thread is used, which requires that the business code and the source code execution process of spring transaction must be in the same thread. For example, in the following code, the child thread inside the method will not be under the control of spring transactions on the M1 method
@Transactional public void m1() {new Thread() {Transactional operations}.start(); }Copy the code
2. How to quickly locate transaction related bugs?
Two kind of way
Method 1: View logs
If you are using logback or log4j to output logs, you can change the log level to DEBUG mode to see detailed transaction execution logs to help you locate errors
Approach 2: Debug the code
If you are familiar with the source code, you will know that a transactions-managed business method executed by Spring is intercepted by the TransactionInterceptor interceptor and entered into its invoke method. We can set some breakpoints in the invoke method and see the detailed execution process. It’s easier to make mistakes.
Overall, you still need to understand the principles, and once you understand the principles, you can avoid a lot of pitfalls when you write code.
Recently, I have organized my personal study notes into a book, which includes Java basics, data structures, JVM, multi-threading, etc. Due to the limited space, only a few interview questions are shown below.
Friends in need can point to get:Click here to get it…Cipher: jj