JTA事务的嵌套
由于前两篇帖子都是关于事务的讨论 (J2EE中的事务处理<script language="javascript" type="text/javascript"> document.title="朝花夕拾 之 J2EE中的事务处理 - "+document.title </script> 、 事务服务浅析),没有讨论到事务嵌套时的解决办法,这两天一直在琢磨,如何才能高效、灵活的解决事务的嵌套问题呢?
既然web容器可以判断当前方法是否处在事务中(JTA事务中提交java.sql.Connection.commit()会报错),那么它是如何判断的呢?带着这个疑问,追查了一下resin容器源码的事务部分,发现了一个类:javax.transaction.Status,用来标明事务状态代码,而javax.transaction.UserTransaction.getStatus()可以取得事务当前的状态!
这样的话,就比较简单了。既然可以随时取得事务的状态编码,而且又能清楚知道每个状态码的含义,就可以对事务进行再次封装了
我的解决办法
package com.javer.test;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
/**
* 事务管理器,对事务再次进行封装
* <p>@author javer QQ:84831612</p>
* @date 2005
*/
public class TransactionManager {
private UserTransaction tx = null;
/**
* 是否自己管理事务(true:自己提交、回滚事务;false:当前事务是嵌套事务,自己不进行事务管理)
*/
private boolean transactionBySelf = true;
private TransactionManager(){}
public static TransactionManager getInstance() throws Exception {
Context ic = new InitialContext();
UserTransaction _tx = (UserTransaction) ic.lookup("java:comp/UserTransaction"); //resin服务器中取得UserTransaction
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:打开事务!");
}//else {
//System.out.println("TransactionManager:已经处于事务中了!所以没有再次打开事务!");
//}
}
public void commitTransaction() throws Exception {
if (tx == null)
return;
if (transactionBySelf) {
tx.commit();
//System.out.println("TransactionManager:提交事务!");
}// else {
//System.out.println("TransactionManager:已经处于事务中了!所以没有提前提交事务!");
//}
}
public void rollbackTransaction() throws Exception {
if (tx == null)
return;
if (transactionBySelf) {
tx.rollback();
//System.out.println("TransactionManager:回滚事务!");
}// else {
//System.out.println("TransactionManager:已经处于事务中了!所以没有提前回滚事务!");
//}
}
}
调用示例
方法a
void a() throws Exception {
TransactionManager tm = TransactionManager.getInstance();
try{
tm.beginTransaction();
System.out.println("JaverTest:数据库操作!");
b(); //调用方法b
tm.commitTransaction();
}catch(Exception e){
tm.rollbackTransaction();
throw e;
}
}
方法b
void b() throws Exception {
TransactionManager tm = TransactionManager.getInstance();
try{
tm.beginTransaction();
System.out.println("JaverTest:数据库操作!");
tm.commitTransaction();
}catch(Exception e){
tm.rollbackTransaction();
throw e;
}
}