![]() ![]() Each such logical transaction scope can determine rollback-only status individually, with an outer transaction scope being logically independent from the inner transaction scope. When the propagation setting is PROPAGATION_REQUIRED, a logical transaction scope is created for each method upon which the setting is applied. If you like, there's an official explanation: That is, no matter if the exception is handled in the first method, the transaction won't be able to commit. If the property value is REQUIRED, which is the default value, the second method will be executed in an existing transaction, and once the rollback condition in the second method is reached, it marks the transaction as rollback-only. When a "transactional" method invokes another "transactional" method, the actual behavior is determined by propagation property of the second annotation. ![]() An UnexpectedRollbackException will be thrown. Unfortunately, it is not happening, we just ran into pitfall 4. Conversely, if persist is called, the transaction will be committed since exceptions should be handled by the try-catch block. Or, we can catch the exception at the first place.Īfter everything is checked, we expect that if unpredictableMethod is called directly and an exception is thrown, the transaction will be rolled back. According to the official document, we can just configure the annotation to rollback for any exception. Nevertheless, I've made this kind of mistake while I was using Java, That's why I think it's worth to mention. In Java language, on the contrary, the exception must be handled or throw to the method caller explicitly, that could make this problem easier to identify. Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration.Īdmittedly, the hidden bug would be much more obvious if I wrote the code segment in Java language, because there isn't any difference between checked exception and runtime exception in Kotlin. ( Errors will also - by default - result in a rollback). In its default configuration, the Spring Framework’s transaction infrastructure code only marks a transaction for rollback in the case of runtime, unchecked exceptions that is, when the thrown exception is an instance or subclass of RuntimeException. By default, Spring won't mark a transaction for rollback after any exception is thrown. Providing only ten lines of code, an experienced Spring developer may realize, "The exception here, is it a runtime exception?". Pitfall 2: annotation may not affect a method invocationįollowing the previous section, after applying the second solution from the previous section, our DemoService now looks like: Let's say we choose to remove the modifier, you can find that the persist is still invoked without any transaction, because we just fall into the next pitfall. ![]() Now the reason is pretty clear, to fix the problem, we can either switch the advice mode from "PROXY"(default option) to "ASPECTJ", or remove the private modifier from the persist method. Consider the use of AspectJ if you need to annotate non-public methods. If you do annotate protected, private or package-visible methods with the annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. When using proxies, you should apply the annotation only to methods with public visibility. "Advice" here refers to a core concept of AOP(read the documentation of Spring AOP to get more information), and there is two different advice mode supported by Spring transaction management, which called "PROXY" and "ASPECTJ". A proxied method invocation procedure looks like this:įrom the picture, it is not hard to imagine that the beginTransaction, commit and rollback logic is implemented in a so called "advice" component. To understand why, we need to know that the declarative transaction is implemented on top of AOP(Aspect Oriented Programming) proxies. In this case, the persist method will be invoked as if no annotation is present. ![]()
0 Comments
Leave a Reply. |