Recently done project encountered a problem of nested transactions, was a hole.
The reason for this is that there is no deep understanding of the meaning of different transactional propagation property configurations in a transaction declaration. Originally imagined is ServiceA method call ServiceB (level Secondary) method with the same transaction to execute, SERVICEB in the execution of the exception, Trycatch B exception and then servicea continue to execute, I will "logical" That MethodA and MethodB each have their own business, the result is indeed ServiceA also throw an exception, because the transaction is gone.
The following references
Propagation_required--Supports the current transaction and creates a new transaction if there is no current transaction. This is the most common choice.
Propagation_supports-supports the current transaction and is executed in a non-transactional manner if no transaction is currently in use.
Propagation_mandatory--Supports the current transaction and throws an exception if there is no current transaction.
Propagation_requires_new--Creates a new transaction and suspends the current transaction if there is a transaction currently in place.
Propagation_not_supported--Performs the operation in a non-transactional manner, suspending the current transaction if a transaction is currently present.
Propagation_never--executes in a non-transactional manner and throws an exception if a transaction is currently present.
Propagation_nested--executes within a nested transaction if a transaction is currently present. If there is currently no transaction, do something similar to propagation_required.
The first six policies are similar to EJB CMT, and the seventh (propagation_nested) is a special variable provided by spring.
It requires the transaction manager or using the JDBC 3.0 savepoint API to provide nested transaction behavior (such as spring's Datasourcetransactionmanager) in the misunderstandings I have seen, the most common are the following:
Reference
If there are two business interfaces ServiceA and SERVICEB, where ServiceA has a method implemented as follows
/**
* Transaction properties configured to Propagation_required
*/
void MethodA () {
Methods for calling ServiceB
Serviceb.methodb ();
}
So if ServiceB's MethodB is configured with a transaction, it must be configured to propagation_nested
This idea may have hurt a lot of people, think that Service should avoid each other to call, in fact, do not have to worry about this, Propagation_required has said very clearly,
If a transaction already exists in the current thread, the method call joins the transaction, and if there is no transaction currently, a new transaction is created, so the transaction of Serviceb#methodb () is configured to propagation_required as long as the most common rule is followed, if ServiceB #methodB (What we call an internal transaction, laying the groundwork for the following) throws an exception, then Servicea#methoda (what we call an external transaction) if there is no special configuration for this exception when the transaction commits (that is, +mycheckedexception usage), Then the whole affair is must be rollback, what service can only tune Dao kind of speech is pure nonsense, spring only is responsible for configuring the transaction attribute method interception, how does it know you this method is in service or Dao?
Say so long, what exactly is the real transaction nesting, explain before we look at Juergen Hoeller's exact words
Juergen Hoeller wrote
Propagation_requires_new starts a NEW, independent "inner" transaction for the given scope. This transaction'll be committed or rolled back completely independent from the outer transaction, have its own Isolat Ion scope, its own set of locks, etc. The outer transaction would get suspended at the beginning of the inner one, and resumed once the inner one have completed.
Such independent inner Transactions is for example used for ID generation through manual sequences, where the access to T He sequence table should happen in its own transactions, to keep the lock there as short as possible. The goal there is to avoid tying the sequence locks to the (potentially much longer running) outer transaction, with the S Equence lock not getting released before completion of the outer transaction.
Propagation_nested on the other hand starts a "NESTED" transaction, which is a true subtransaction of the existing one. What would happen is a savepoint would be taken at the start of the nested transaction. ÍF the nested transaction fails, we'll roll back to that savepoint. The nested transaction is part of the of the outer transaction, so it would be only being committed at the end of the outer Transa Ction.
Nested transactions essentially allow to try some execution subpaths as subtransactions:rolling the Beginning of the failed subpath, continuing with another subpath or with the main execution path There-all within one is olated transaction, and not losing any previous work done within the outer transaction.
For example, consider parsing a very large input file consisting of account transfer blocks:the entire file should essent Ially is parsed within one transaction, with one single commit at the end. But if a block fails, it transfers need to being rolled back, writing a failure marker somewhere. You could either start over the entire transaction every time a block fails, remembering which blocks to skip-or your Mar K each block as a nested transaction, only rolling back that specific set of operations, keeping the previous work of the Outer transaction. The latter is of course much more efficient, in particular when a block at the end of the file fails.
Juergen Hoeller wrote
Rolling back the entire transaction are the choice of the demarcation code/config that started the outer transaction.
So if a inner transaction throws an exception and are supposed to being rolled back (according to the rollback rules), the TR Ansaction'll get rolled back to the savepoint taken at the start of the inner transaction. The immediate calling code can then decide to catch the exception and proceed off some other path within the outer Transa Ction.
If the code that called the inner transaction lets the exception propagate up the call chain, the exception would eventuall Y reach the demarcation Code of the outer transaction. At this point, the rollback rules of the outer transaction decide whether to trigger a rollback. That would is a rollback of the entire outer transaction then.
So essentially, it depends on your exception handling. If you catch the exception thrown by the inner transaction, you can proceed down some other path within the outer transact Ion. If you let the exception propagate up the call chain, it ' s eventually gonna cause a rollback of the entire outer transacti On.
In other words, the most confusing is actually propagation_requires_new and propagation_nested, then what is the difference between these two ways? I simply translated the words of Juergen Hoeller:
Propagation_requires_new starts a new, "internal" transaction that does not depend on the environment. This transaction will be fully commited or rolled back without relying on external transactions, it has its own isolation range, its own locks, and so on. When an internal transaction starts executing, the external transaction will be suspended and the external transaction will continue to execute at the end of the housekeeping transaction.
On the other hand, propagation_nested begins a "nested" transaction, which is a real child of a transaction that already exists. When the dive set starts executing, it will get a savepoint. If this nested transaction fails, we will roll back to this savepoint. A latent transaction is a part of an external transaction that is committed only after the external transaction has ended.
Thus, the biggest difference between propagation_requires_new and propagation_nested is that propagation_requires_new is entirely a new business, and propagation_nested is a child of an external transaction, and if an external transaction commits, a nested transaction is also commit, and the same rule applies to roll back.
So how do external transactions take advantage of the savepoint characteristics of nested transactions, and we use code to speak
Java code SERVICEA {/** * Transaction property is configured as propagation_required */void MethodA () {Servic Eb.methodb (); }} SERVICEB {/** * Transaction property is configured as Propagation_requires_new */void MethodB () { } }
In this case, because the transaction property of Serviceb#methodb is Propagation_requires_new, there is no relationship between the two, Servicea#methoda and Serviceb#methodb Does not affect the outcome of the transaction because of the execution of the other, because they are two transactions at all, and Servicea#methoda's transaction has been suspended when Serviceb#methodb executes (the contents of the transaction hang are beyond the scope of this article. I'll write some more hanging articles when I have time.
So what happened to propagation_nested? Continue looking at the code
Java code SERVICEA {/** * Transaction property is configured as propagation_required */void MethodA () {Servic Eb.methodb (); }} SERVICEB {/** * transaction property configured to propagation_nested */void MethodB () {} }