Document directory
- JTA transaction nesting
- My solution
- Call example
JTA transaction nesting
Since the previous two posts were about transactions (transaction processing and Transaction Service Analysis in J2EE), the solution to transaction nesting was not discussed, and we have been pondering over these two days, how can we efficiently and flexibly solve the problem of transaction nesting?
Since the Web Container can determine whether the current method is in a transaction (an error is reported when java. SQL. Connection. Commit () is committed in a JTA transaction), how can it determine? With this question, I traced the transaction part of the resin container source code and found a class: javax. transaction. status, used to indicate the transaction status code, while javax. transaction. usertransaction. getstatus () can get the current state of the transaction!
In this case, it is relatively simple. Since the status code of the transaction can be obtained at any time and the meaning of each status code can be clearly understood, the transaction can be re-encapsulated.
My solution
Package com. javer. test;
Import javax. Naming. context;
Import javax. Naming. initialcontext;
Import javax. transaction. status;
Import javax. transaction. usertransaction;
/**
* The Transaction Manager encapsulates the transaction again.
* <P> @ author javer QQ: 84831612 </P>
* @ Date 2005
*/
Public class transactionmanager {
Private usertransaction Tx = NULL;
/**
* Whether to manage the transaction by yourself (true: Submit and roll back the transaction by yourself; false: The current transaction is a nested transaction, and you do not manage the transaction yourself)
*/
Private Boolean transactionbyself = true;
Private transactionmanager (){}
Public static transactionmanager getinstance () throws exception {
Context Ic = new initialcontext ();
Usertransaction _ Tx = (usertransaction) IC. Lookup ("Java: COMP/usertransaction"); // obtain usertransaction from the Resin server
Transactionmanager TM = new transactionmanager ();
TM. Tx = _ TX;
If (_ Tx. getstatus ()! = Status. status_no_transaction)
TM. transactionbyself = false;
Return TM;
}
Public void begintransaction () throws exception {
If (Tx = NULL)
Return;
If (TX. getstatus ()! = Status. status_no_transaction)
Transactionbyself = false;
If (transactionbyself ){
TX. Begin ();
// System. Out. println ("transactionmanager: Open the transaction! ");
} // Else {
// System. Out. println ("transactionmanager: it is already in the transaction! So the transaction is not opened again! ");
//}
}
Public void committransaction () throws exception {
If (Tx = NULL)
Return;
If (transactionbyself ){
TX. Commit ();
// System. Out. println ("transactionmanager: Submit a transaction! ");
} // Else {
// System. Out. println ("transactionmanager: it is already in the transaction! So no transactions were submitted in advance! ");
//}
}
Public void rollbacktransaction () throws exception {
If (Tx = NULL)
Return;
If (transactionbyself ){
TX. rollback ();
// System. Out. println ("transactionmanager: roll back the transaction! ");
} // Else {
// System. Out. println ("transactionmanager: it is already in the transaction! So the transaction is not rolled back in advance! ");
//}
}
}
Call example
Method
Void A () throws exception {
Transactionmanager TM = transactionmanager. getinstance ();
Try {
TM. begintransaction ();
System. Out. println ("javertest: database operation! ");
B (); // call Method B
TM. committransaction ();
} Catch (exception e ){
TM. rollbacktransaction ();
Throw E;
}
}
Method B
Void B () throws exception {
Transactionmanager TM = transactionmanager. getinstance ();
Try {
TM. begintransaction ();
System. Out. println ("javertest: database operation! ");
TM. committransaction ();
} Catch (exception e ){
TM. rollbacktransaction ();
Throw E;
}
}