I have a chain of method calls where A开发者_如何学C calls B that calls C that calls D. A and D have @Transactional annotation. but B and C doesn't. what is the scope of transaction boundaries in this case. are B and C part of the transaction at all?
By default A, B, C & D work in the same transaction. The default propagation level of a transaction is TX_REQUIRED meaning a new transaction is started if one does not exist (A starts one, B, C, D participates).
D could start a new transaction by setting its propagation level to TX_REQUIRES_NEW (if your environment supports it). In that scenario, when D is done the suspended transaction is resumed. Committing D does not affect the outcome of transaction A. Rollbacking A will not rollback D (already committed) as they are separate transactions.
Also, a lot of developers forgets that only public method may be marked @Transactional as Spring uses proxies to manage the transactions (private/protected methods are called on "this" - thus the proxy has no chance to do its magic). This does not necessiraly hold true if you are using byte code injection instead of proxies.
If you wish to learn more about transaction design patterns, I strongly suggest the following ebook (free! - registration required): http://www.infoq.com/minibooks/JTDS. It is a very straightforward read.
That depends on the propagation parameter of the @Transactional
annotation.
Per default, everything that happens within A is part of one single transaction - that includes all methods called directly and indirectly by it.
Other propagation mode would allow D to suspend the current transaction and start its own, execute in a nested transaction, or throw an exception because it's not meant to be used within an existing transaction.
Independent of what happens:
if this question even comes up, you probably have serious design problems.
in 95% of cases, Transaction demarcation should take place at the entry point of your application, that is in a service method that calls all the other code internally.
The only valid case I can think of where one @Transactional
method calls another is when the inner method has propagation REQUIRES_NEW
. If that is not the case: refactor your design, so that your code only passes through a single @Transactional
annotation.
If you call B and C from a @Transactional A, they will still be in a transaction.
Have a look at transaction propagation in spring docs.
精彩评论