Spring declarative transactions fail in the same class of method invocation transactions

Source: Internet
Author: User

Problem

Spring's declarative transactions, I think there is no more introduction, a sentence "Since the use of Spring AOP Ah, the transaction management is very easy ah, really easy; transaction management code No, the brain is not sour, the hand is not painful, all in one breath with the business; lightweight, easy to test, hey! ”。 From any angle, lightweight declarative transactions are a great thing to liberate productivity. So, we "always use it".

However, in a recent project, there has been a transaction management problem: There is a service class, a declaration of the transaction method, which did three insert SQL operations, but in the back of the error rollback, but found that the previous insert succeeded, also said that the method of declaring the transaction, actually did not really start the transaction! What's going on here? Does spring's declarative transaction fail?

[Explore]

In fact, some people have said that spring's transaction configuration does not work, but according to the first reaction and past experience, I always tell him that there must be a problem with your configuration, so this time, I think it is no exception, presumably to put the transaction annotations on the interface rather than the implementation method, or, If it is declared in XML, it is likely that the pointcut expression is not paired.

However, after checking their configuration, but found that there is no configuration problem, the implementation of the transaction, using the @transactional transaction annotation declaration, the XML is also equipped with the annotated driver <tx:annotation-driven .../> configuration is right. How could it not work?

I was very puzzled, and then asked:

Q 1: Is there any other way of doing this?

Answer 1: No.

Q 2: Is there anything special about this method (hereinafter referred to as method B)?

A 2: Is the background inserted three records Ah, nothing special.

Q 3: Is this method called directly from the Web layer?

Answer 3: No, it is another method of this service class (hereinafter referred to as SERVICEA) that is transferred (hereinafter referred to as method a).

Q 4: Oh, does the method that calls it match the transaction (the problem may be here)?

Answer 4: No.

Q 5: The Web Layer action (with STRUTS2), called method a without declaring the transaction, method A then invokes method B that declares the transaction?

Answer 5: Yes.

Q 6: You add a transaction statement directly on method A to see

Answer 6: Ok ...

Seems likely to find the problem, so the @transactional also added to method A, start the project test, the result is: The transaction is in effect, both method A and method B are in one transaction.

OK, now summarize the phenomenon:

1, ServiceA class for the Web Layer Action Service

2. Action calls ServiceA method A, and method A does not declare the transaction (because method a itself is time consuming and does not require a transaction)

3. ServiceA method A calls its own method B, and Method B declares the transaction, but the transaction declaration of method B fails in this case.

4. If a transaction is also declared on method A, the transaction takes effect when action calls method A, and method B automatically participates in the transaction.

I asked him to add a business statement and decided to come back and test it.

This problem, on the surface, is the problem of the failure of the transaction declaration, which is probably the problem of the implementation of the spring AOP mechanism. I think of a phenomenon that was discovered a long time ago when researching the implementation of the AOP in spring: For an AOP target class that is enhanced by cglib, two objects are created, one instance of the bean instances itself, and one is the Cglib enhanced proxy object, not just the latter. I had doubts about it, but I did not go into it carefully.

We know that there are two types of AOP implementations in spring: 1, Java proxy mode, 2, cglib dynamic enhancement, both of which can be seamlessly and freely switched in spring. The advantage of the Java proxy approach is that it does not rely on third-party jar packages, and the disadvantage is that it cannot proxy classes, only proxy interfaces.

Spring uses the Aopproxy interface to abstract both implementations, implementing a consistent approach to AOP:

Now it seems that this abstraction also has a flaw, which is to erase the ability of cglib to directly create an enhanced subclass of the ordinary class, which is equivalent to the Cglib dynamically generated subclass, when the normal proxy class, which is why the creation of two objects. Shows the actual invocation procedure of spring's AOP proxy class:

Therefore, as can be seen from the above analysis, MethodB is not notified by the Aopproxy, resulting in the end result is: The spring AOP enhanced class, in the same class's internal method invocation, its called method on the enhanced notification will not work.

And what effect would this result be:

1: The transaction declaration of the invoked method will not work when called internally

2: In other words, when you declare on a method that it needs a transaction, if there are other developers in this class, you will not be able to guarantee that the method will really be in the transactional context

3: In other words, spring's transactional propagation policy will not work in an internal method call. Whether you want a method to need a separate transaction, a requiresnew, a nested transaction, a nested, and so on, it doesn't work.

4: Not just transaction notifications, all of your own AOP notifications implemented with spring are subject to the same limitations ....

Problem solving

The cause of the problem has been found, in fact, my ideal AOP implementation, should be the following:

As long as a cglib enhance the object is good, for the Java Proxy way, my choice is not hesitate to abandon.

As for the previous transaction problem, just avoid the limitations of spring's current AOP implementation, either declare a transaction, or divide it into two classes, or use programmatic transactions directly in the method, then all OK.

Original address: http://blog.csdn.NET/seelye/article/details/40144817

Spring declarative transactions fail in the same class of method invocation transactions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.