public class UserTransaction {
private static Map threadDbconnectionMap = new HashMap();
public void begin() {
dataSource.getConnection().setAutoCommit(false);
threadDbConnectionMap.put(Thread.currentThread(), dataSource.getConnection());
dataSource.getConnection().startTransaction();
}
public void commit() {
dataSource.getConnection().commitTransaction();
threadDbConnectionMap.remove(Thread.currentThread());
}
}
public class DataSource {
private static Map threadDbConnectionMap = new HashMap();
public Connection getConnection() {
if(threadDbConnectionMap.get(Thread.currentThread()) == null) {
threadDbConnectionMap.put(Thread.currentThread(), DBCONNECTION_POOL.getConnection);
}
return (Connection)threadDbConnectionMap.get( Thread.currentThread());
}
}
UserTransaction的机制就是建立一个currentThread和一个 DBconnection的map,使得在同一个thread下的所有db operation使用同一个connection,这样通过背后的同一个connection的commit或rollback来保证 transaction的atomic
public class DBConnectionPool {
// singleton Pattern
public Connection fetchConnection() ;
public void releaseConnection(Connection conn);
}
public class ThreadConnectionMap {
// singleton pattern.
private Map threadConnectionMap = new HashMap();
public Connection getConnection() {
if(threadConnectionMap.get(Thread.currentThread()) != null) {
return (Connection)threadConnectionMap.get(Thread.currentThread());
}
return DBConnectionPool.fetchConnection();
}
public Connection getConnectionInTx() {
return (Connection)threadConnectionMap.get(Thread.currentThread());
}
public void releaseConnectionInTx() {
Connection con = getConnectionInTx();
threadConnectionMap.remove(Thread.currentThread());
DBConnectionPool.releaseConnection(con);
}
public Connection newConnectionInTx() {
if(inTransaction()) {
throw new TransactionException("Transaction already started!");
}
Connection conn = DBConnectionPool.fetchConnection();
threadConnectionMap.put(Thread.currentThread(), conn);
return conn;
}
public boolean inTransaction() {
return threadConnectionMap.get(Thread.currentThread()) != null;
}
..............
}
public class VendorDataSource() implements javax.sql.DataSource {
public Connection getConnection() {
return ThreadConnectionMap.getConnection();
}
..........
}
public class VendorUserTransaction implements javax.transaction.UserTransaction {
public void begin() {
Connection con = ThreadConnectionMap.newConnectionInTx();
con.setAutoCommit(false);
}
public void commit() {
Connection con = ThreadConnectionMap.getConnectionInTx();
if(con == null) {
throw new TransactionException("cannot commit transaction, UserTransaction not started!");
}
con.commit();
ThreadConnectionMap.releaseConnectionInTx();
}
public void rollback(){
Connection con = ThreadConnectionMap.getConnectionInTx();
if(con == null) {
throw new TransactionException("cannot rollback transaction, UserTransaction not started!");
}
con.rollback();
ThreadConnectionMap.releaseConnectionInTx();
}
public boolean inTransaction() {
return ThreadConnectionMap.inTransaction();
}
....
}
以上是没有考虑XA(distributed transaction)和连接多个数据库情况的TransactionManager的实现,非常简陋,只是用于说明JTA的原理
[color=red]1。由于你只是使用了web server,没有采用application server,你的application又需要提供Transaction的control,唯一的办法是提供你自己的Transaction Manager,而不是使用UserTransaction(正如你所说的,web server不提供UserTransaction)。UserTransaction也是一种TransactionManager,由J2EE Container提供。
2。你的“dbConnection.setAutoCommit(true)”这个调用是错误的。如果你调用该语句,dbConnection就会每次execute一句sql以后自动commit了,这样你的程序中本身需要放在同一个transaction中执行的代码分散在了好几个不同的transaction中执行了,就会导致partial update的问题,data consistency就没有办法保证。
3。“死锁”的问题应该是你程序中的问题,而不应该归咎于dbConnection是否是 auto commit的。我在以前曾经写过一个自己的TransactionManager,就是通过建立一个Thread和dbConnection的map来实现的。刚开始测试这个TransactionManager的时候,也是经常出现“死锁”的问题,最后debug的结果发现并不是auto commit的问题,而是对于thread synchronization的问题处理不得当所导致的。
4。“手动地为每一个更新都编写一个恢复原始数据的方法”是错误的。试想想,如果在你手动恢复数据的过程中又出现了Exception,你又如何保证data consistency呢?
5。自己编写TransactionManager是一件比较复杂的工作,不是我想建议的。这也是为什么banq强烈推荐EJB的原因。EJB提供了TransactionManager的功能,我们可以采用EJB的解决方案,just off-the-shelf,不是吗?或者用JTA和DataSource一道实现Transaction的control。
6。如果你必须要采用自己编写的TransactionManager,我可以讲解一下J2EE CONTAINER所提供的JTA/JTS的实现原理,或许对于你编写自己的TransactionManager有一定的帮助。
7。我们知道在J2EE Spec中提供了UserTransaction和DataSource的interface的定义,具体是如何实现的留给那些J2EE Container的vendor来实现,对于application developer来说他所能见到的就是这两个interface。对于支撑这两个interface背后的东西,application developer是永远都不可能知道的。看看下面的architecture吧
User-defined Application API
----------------------------
UserTransaction DataSource
----------------------------
DBConnectionPool ThreadConnectionMap
(XAConnection, XAResource, XADataSource)
我们清楚的看到,对于UserTransaction,DataSource的支持离不开我们所看不到的J2EE spec中的一些定义,对于application developer来说,它隐藏了这些东西的复杂性。与application developer打交道的只是UserTransaction和DataSource。[/color]
http://www.jdon.com/jivejdon/thread/12894.html