In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly shows you "what to do when the @ Transactional annotation fails in Spring". It is easy to understand and clear. I hope it can help you solve your doubts. Let the editor lead you to study and learn this article "what to do when the @ Transactional annotation fails in Spring".
After I found out that I used @ Transactional to annotate transactions in the project these days, I threw an exception and didn't roll back. And then I finally found out why. If this happens to you, you can start the investigation below.
I. characteristics
Let's first take a look at the features of @ Transactional annotated transactions to better troubleshoot problems.
1. Add @ Transactional to the service class tag (generally not recommended) to incorporate the entire class into spring transaction management. A transaction is opened when each business method executes, but these transactions are managed in the same way.
2. @ Transactional annotations can only be applied to public visibility methods. If applied to protected, private, or package visibility methods, there will be no error, but transaction settings will not work.
3. By default, Spring rolls back unchecked exceptions by transaction; if it is an checked exception, it does not roll back. What is the checked exception and what is the unchecked exception
In java, exceptions derived from Error or RuntimeException (such as null pointer, 1ap0) are called unchecked exceptions, and other exceptions inherited from java.lang.Exception are collectively called Checked Exception, such as IOException, TimeoutException, etc.
Hot more popular: you write code null pointer and other exceptions will be rolled back, file reading and writing, network problems, spring will not be able to roll back. Then I will teach you how to remember this, because many students are easy to get confused. When you write code, some IOException can be detected by our compiler, so it is called checked exception. When you write code, the null pointer cannot be detected, so it is called unchecked exception. Isn't that easier to remember?
4. Read-only transactions
@ Transactional (propagation=Propagation.NOT_SUPPORTED,readOnly=true)
The read-only flag is applied only when the transaction starts, otherwise even the configuration will be ignored.
Starting a transaction increases thread overhead, and the database is locked due to shared reads (depending on the database type and transaction isolation level). In general, there is no need to set up read-only transactions to add additional system overhead when only reading data.
Second, transaction communication mode
Propagation enumerates a variety of transaction propagation modes, some of which are as follows:
1. REQUIRED (default mode): business methods need to run in a container. If the method is already in a transaction when it is running, join the transaction, otherwise create a new transaction yourself.
2. NOT_SUPPORTED: declare that the method does not require a transaction. If the method is not associated with a transaction, the container will not open the transaction for him, if the method is called in a transaction, the transaction will be suspended, and after the call ends, the original transaction will resume execution.
3. REQUIRESNEW: this method always initiates a new transaction for itself, regardless of whether there is a transaction or not. If the method is already running in a transaction, the original transaction is suspended and a new transaction is created.
4. MANDATORY: this method can only be executed in an existing transaction, and the business method cannot initiate its own transaction. If called without a transaction, the container throws an exception.
5. SUPPORTS: if the method is called within the scope of a transaction, the method becomes part of the transaction. If the method is called outside the scope of the transaction, the method is executed in an environment where there is no transaction.
6. NEVER: this method must not be executed within the scope of a transaction. Make an exception if you are here. The method executes normally only if the method is not associated with any transaction.
7. NESTED: if an active transaction exists, it runs in a nested transaction. If there is no active transaction, press the REQUIRED property to execute. It uses a separate transaction that has multiple Savepoints that can be rolled back. The rollback of the internal transaction does not affect the external transaction. It works only for DataSourceTransactionManager transaction managers.
Third: solve the problem that Transactional comments will not be rolled back
1. Check whether your method is public.
2. Is your exception type unchecked exception? what if I want to roll back the check exception? just write down the exception type on the note.
@ Transactional (rollbackFor=Exception.class)
Similarly, there are norollbackFor, custom exceptions that are not rolled back.
3. The database engine should support transactions. If it is MySQL, note that the table should use an engine that supports transactions, such as innodb. If it is myisam, transactions will not work.
4. Whether the parsing of annotations is enabled
5. Whether your package is scanned by spring. Here is the package scanned under org.test.
6. Check whether it is a method call in the same class (for example, a method calls a method in the same class)
7. Is the anomaly occupied by you catch?
Question: why do transaction annotations fail when the method modifier is not public?
In the past few days, my colleague encountered a problem. He cut into Controller in the direction of Aop and logged the request. As a result, the method of adjusting the Service layer reported a null pointer error, because service was not injected. The @ Autowired and @ Resource annotations are not injected. Line by line of check code, there are no errors, and then can only be deleted by a method, to see where can be run, the result is because the Controller method is private private type. Later, it was changed to public.
Doesn't seem to be able to intercept private methods?
I've tried many times, but I've all failed, isn't it?
I thought about it for a moment, because the bottom layer of aop is the agent.
Jdk is a proxy interface, and private methods must not exist in the interface, so they will not be intercepted.
Cglib is a subclass, and private's methods still do not appear in the subclass and cannot be intercepted.
Instead of calling methods directly within the class, I maintain a proxy for my own instance
Execution (* test.aop.ServiceA.* (..))
Public class ServiceA {private ServiceA self; public void setSelf (ServiceA self) {this.self = self;} public String methodA (String str) {System.out.println ("methodA: args=" + str); self.methodB ("b"); return "12345" + str;} private String methodB (String str) {System.out.println ("methodB: args=" + str); self.methodC ("c"); return "12345" + str } public String methodC (String str) {System.out.println ("methodC: args=" + str); return "12345" + str;}}
Is that what happened? But on stackoverflow, some people say that it works fine
Execution (public * test.aop.ServiceA.* (..)
There is also a strange phenomenon. If there is no write permission in execution, then all public protected package methods can be blocked.
If you write public, you can only intercept the public method.
If he wrote protected, he would do nothing, even the protected method would not intercept.
Analysis.
The private method using pure Spring AOP in Spring (only public/protected/ packets can be intercepted) cannot be intercepted because subclasses cannot be overridden; the package level can be intercepted because subclasses and parents can be overridden in the same package.
In the case of cglib agent, execution (* * (..)) You can intercept public/protected/ package-level methods (that is, these methods can be proxied).
Private static boolean isOverridable (Method method, Class targetClass) {if (Modifier.isPrivate (method.getModifiers () {return false;} if (Modifier.isPublic (method.getModifiers ()) | | Modifier.isProtected (method.getModifiers () {return true;} return getPackageName (method.getDeclaringClass ()) .equals (getPackageName (targetClass));}
If you want to implement the interception private method, you can use native AspectJ compile-time / run-time weaving.
Quote
If he wrote protected, he would do nothing and not even intercept the protected method; this should not
The basic analysis of the reason is clear:
The judgment code for whether the enhancement can be applied is as follows (org.springframework.aop.support.AopUtils):
Public static boolean canApply (Pointcut pc, Class targetClass, boolean hasIntroductions) {if (! pc.getClassFilter (). Matches (targetClass)) {return false;} MethodMatcher methodMatcher = pc.getMethodMatcher (); IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;} Set classes = new HashSet (ClassUtils.getAllInterfacesForClassAsSet (targetClass)); classes.add (targetClass); for (Iterator it = classes.iterator (); it.hasNext ();) {Class clazz = (Class) it.next (); Method [] methods = clazz.getMethods () For (int j = 0; j < methods.length; jacks +) {if ((introductionAwareMethodMatcher! = null & & introductionAwareMethodMatcher.matches (methods [j], targetClass, hasIntroductions)) | | methodMatcher.matches (methods [j], targetClass)) {return true;} return false;}
Here Method [] methods = clazz.getMethods (); you can only get the public method.
Scene 1:execution (* * (..))
Public class Impl2 {protected/public String testAop2 () {System.out.println; return "1233";}}
Because the pointcut does not have an access modifier, that is, it can be arbitrary, so the canApply method can get a public method such as wait, that is, it can implement a proxy.
Scene 2:execution (public * * (..))
Public class Impl2 {public String testAop2 () {System.out.println; return "1233";}}
Because it intercepts public, the canApply method can get public methods such as wait, that is, it can implement proxies.
Scene 3:execution (protected * * (..))
Public class Impl2 {protected String testAop2 () {System.out.println; return "1233";}}
Remember that Method [] methods = clazz.getMethods () in the canApply method can only get the public method, so it doesn't match the protected access modifier, so if "execution (protected * * (..)" Can't be represented.
That's why execution (protected * (..)) Why it doesn't work in a pure Spring AOP environment.
Note: special case of @ Transactional annotated transaction:
Quote
Visibility of the method and @ Transactional
When using proxies, the @ Transactional annotation should only be applied to public visibility methods. If you use @ Transactional annotations on protected, private, or package-visible methods, the system will not report an error, but this annotated method will not execute the configured transaction settings.
The above is all the content of the article "what to do when the @ Transactional annotation fails in Spring". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.