事务管理(二) JDBC事务管理简单实现

概述:
为了学习事务的管理,实现了如下的一个简单版本的事务管理器,进行实验。该管理器简化了事务管理的各种异常类型的考虑。

对于Transaction 管理
为了实现数据一致性,对于数据库的JDBC编程通常需要在代码中显示的调用Connection方法的事务相关API来完成工作。
常见的代码如下:
Java代码   收藏代码
  1. public void doService(){  
  2.     Connection connection = getConnection();  
  3.     connection.setTransactionIsolation(  
  4.     Connection.TRANSACTION_READ_COMMITTED);  
  5.     try{  
  6.         doBusinessLogic(connection);  
  7.         connection.commit();  
  8.     }catch(Exception e){  
  9.         connection.rollback();  
  10.     }finally{  
  11.         connection.close();  
  12.     }  
  13. }  


在以上的代码中与业务逻辑相关的代码只有一行, 为了简化事务的操作,实现一个简单的事务管理控制。主要提供以下方面的统一控制。
1.使用回调机制简化事务处理的代码
2.增加对事务隔离级别的支持
3.增加事务Timeout的管理,最简单的实现。 尽早发现长事务的操作。
4.对于savepoint的支持
5.实现一种事务传播控制。 如果当前存在事务,就加入该事务中执行,如果没有新建事务,放到事务中实现。

实现了该事务控制管理器后,将Service的代码得到如下的简化:
Java代码   收藏代码
  1. private Service service;  
  2. private Dao dao;  
  3. private TransactionTemplate transactionTemplate;  
  4. public void service(final Object obj) {  
  5.     this.trTemplate.executeTransaction(new TransactionCallback(){  
  6.       public Object doTransactionEvent() {  
  7.         service.doService();  
  8.         transactionTemplate.addSavePoint("savepoint1", exception1);  
  9.         dao.saveMethod1(obj);  
  10.         transactionTemplate.addSavePoint("savepoint2", exception2);  
  11.         dao.saveMethod2(obj);  
  12.       }  
  13.     });       
  14. }  


1. 回调的实现
定义模板类TransactionTemplate
其主要的方法就是提供模板方法对事务处理的代码进行控制:
Java代码   收藏代码
  1. public class TransactionTemplate {  
  2.       
  3.     private TransactionManager trManager;  
  4.       
  5.     //the timeout monitor is used to find out all long time transaction in advance.  
  6.     private boolean useTimeoutMonitor = Boolean.TRUE;  
  7.     private Long maxTime = Long.valueOf(2);  
  8.       
  9.     public void addSavePoint(String savePointName, Exception rollbackException){  
  10.         this.trManager.addSavePoint(savePointName, rollbackException);  
  11.     }  
  12.       
  13.     public void executeTransaction(  
  14.   TransactionCallback transactionCallback, int isolationLevel) {  
  15.         long startTime = System.currentTimeMillis();  
  16.         Transaction transaction = null;  
  17.         try{  
  18.             transaction = trManager.beginTransaction();  
  19.             checkTimeout(startTime);  
  20.             transaction.setTransactionIsolationLevel(isolationLevel);  
  21.             transactionCallback.doTransactionEvent();  
  22.             checkTimeout(startTime);  
  23.             trManager.commitTransaction(transaction);  
  24.         }catch(Exception e){  
  25.             trManager.rollbackTransaction(transaction, e);  
  26.               
  27.         }finally{  
  28.             trManager.closeTransaction(transaction);  
  29.         }  
  30.           
  31.     }  
  32.   
  33.     /** 
  34.      * If the transaction is timeout throw a transaction time out exception. 
  35.      */  
  36.     private void checkTimeout(long startTime) {  
  37.         ifthis.useTimeoutMonitor ){  
  38.             if(isTimeout(startTime)){  
  39.                 throw new TransactionTimeoutException();  
  40.             }  
  41.         }  
  42.     }  
  43.       
  44.     private boolean isTimeout(long startTime) {  
  45.         return System.currentTimeMillis() - startTime > this.maxTime ;  
  46.     }  
  47.   
  48.     public void executeTransaction(TransactionCallback transactionCallback){  
  49.         this.executeTransaction(transactionCallback, Transaction.DEFAULT_ISOLATION_LEVEL);  
  50.       
  51.     }  
  52.   
  53.     public Long getMaxTime() {  
  54.         return maxTime;  
  55.     }  
  56.   
  57.     public void setMaxTime(Long maxTime) {  
  58.         this.maxTime = maxTime;  
  59.     }  
  60.   
  61. }  


2. 回调接口的定义非常的简单:
Java代码   收藏代码
  1. public interface TransactionCallback {  
  2.     public Object doTransactionEvent();  
  3. }  


3. 重点Transaction类的实现,管理了Connection对象,事务隔离级别的定义,事务的savepoint控制点,以及对于事务状态的控制。

Java代码   收藏代码
  1. public class Transaction {  
  2.     public static final int READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;   
  3.     public static final int READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;   
  4.     public static final int REPEATALB_READ = Connection.TRANSACTION_REPEATABLE_READ;  
  5.     public static final int SERIALIZE = Connection.TRANSACTION_SERIALIZABLE;  
  6.     public static final int DEFAULT_ISOLATION_LEVEL = READ_COMMITTED;  
  7.       
  8.     private Map<Exception,Savepoint> savePoints = new HashMap<Exception, Savepoint>();  
  9.       
  10.     //This count is used to implement the transaction propagation    
  11.     private int newTrCount = 1;  
  12.   
  13.     Connection connection;  
  14.       
  15.       
  16.     public Transaction(Connection connection){  
  17.         this.connection = connection;  
  18.     }  
  19.       
  20.     public void addNewService(){  
  21.         this.newTrCount++;  
  22.     }  
  23.       
  24.     public void completeService(){  
  25.         this.newTrCount--;  
  26.     }  
  27.       
  28.     public boolean isNewTransaction(){  
  29.         return this.newTrCount == 1;  
  30.     }  
  31.   
  32.     /** 
  33.      * @return the connection 
  34.      */  
  35.     public Connection getConnection() {  
  36.         return connection;  
  37.     }  
  38.   
  39.     /** 
  40.      * @param connection the connection to set 
  41.      */  
  42.     public void setConnection(Connection connection) {  
  43.         this.connection = connection;  
  44.     }  
  45.   
  46.     /** 
  47.      * @param transactionIsolationLevel the transactionIsolationLevel to set 
  48.      * @throws SQLException  
  49.      */  
  50.     public void setTransactionIsolationLevel(int transactionIsolationLevel) throws SQLException {  
  51.         this.connection.setAutoCommit(false);  
  52.         this.connection.setTransactionIsolation(transactionIsolationLevel);  
  53.     }  
  54.       
  55.     public void addSavepointAndRollbackException(String name, Exception e)   
  56.         throws SQLException{  
  57.         Savepoint savepoint = this.addSavePoint(name);  
  58.         this.savePoints.put(e, savepoint);  
  59.     }  
  60.       
  61.     public boolean isSupportSavepoint() throws SQLException{  
  62.         return this.getConnection().getMetaData().supportsSavepoints();  
  63.     }  
  64.       
  65.     private Savepoint addSavePoint(String savepointName) throws SQLException{  
  66.         return this.connection.setSavepoint(savepointName);  
  67.     }  
  68.   
  69.     public boolean containsSavepoint() {  
  70.         return !this.savePoints.isEmpty();  
  71.     }  
  72.   
  73.     public Savepoint getSavePointByException(Exception e) {  
  74.         return this.savePoints.get(e);  
  75.     }  
  76.   
  77. }  

1) 对于savePoints属性记录了所有的事务的保存点,当service运行抛出Exception时,将进入rollback逻辑,这个时候,rollback方法会查找相应的Exception的保存点,将事务回滚到该保存点。
具体的保存点检查代码如下:
public void addSavepointAndRollbackException(String name, Exception e)

public boolean isSupportSavepoint() throws SQLException{}

private Savepoint addSavePoint(String savepointName) throws SQLException{}

public boolean containsSavepoint() {}

public Savepoint getSavePointByException(Exception e) {}

2) 属性newTrCount主要是用于实现事务的传播控制。当且仅当该值为1时候表示该事务是新创建的一个事务。当一个service运行的时候,如果发现当前的service线程已经有事务对象,那么这个时候就不需要再重新创建事务,只需要将原有的事务对象的计数器加1,那么相应的当该Serice运行完成才将事务减一,从而保证只有最外层的service看到的事务对象是新创建的事务对象,会执行真正的事务操作,而其他嵌套的Service对象,只是对该count进行操作。
提供了如下的三个方法方便控制:
public void addNewService(){
    this.newTrCount++;
}

public void completeService(){
    this.newTrCount--;
}

public boolean isNewTransaction(){
    return this.newTrCount == 1;
}

4. 核心对象TransactionManager 该对象管理了Transaction对象,并且控制着事务的操作。
其代码如下
Java代码   收藏代码
  1. public class TransactionManager {  
  2.       
  3.     private ConnectionManager connectionManager;  
  4.       
  5.     private ThreadLocal<Transaction> transactions = new ThreadLocal<Transaction>();  
  6.       
  7.     public Transaction beginTransaction() {  
  8.         try{  
  9.             Transaction tr = this.transactions.get();  
  10.             if( tr == null ){  
  11.                 Connection connection = connectionManager.getConnection();  
  12.                 connectionManager.setTransactionActive(true);  
  13.                 tr = new Transaction(connection);  
  14.                 this.transactions.set(tr);  
  15.             }else{  
  16.                 tr.addNewService();  
  17.             }  
  18.             return tr;  
  19.         }catch(Exception e){  
  20.             throw new TransactionException();  
  21.         }  
  22.     }  
  23.       
  24.     public void commitTransaction(Transaction transaction) {  
  25.         try{  
  26.             if( transaction.isNewTransaction() ){  
  27.                 connectionManager.setTransactionActive(false);  
  28.                 connectionManager.commit(transaction.getConnection());  
  29.             }  
  30.         }catch(Exception e){  
  31.             throw new TransactionException();  
  32.         }  
  33.     }  
  34.       
  35.     public void rollbackTransaction(Transaction transaction, Exception e) {  
  36.         try{  
  37.             if( transaction.isNewTransaction() ){  
  38.                 connectionManager.setTransactionActive(false);  
  39.                 if(transaction.containsSavepoint()){  
  40.                     Savepoint savepoint = transaction.getSavePointByException(e);  
  41.                     if( savepoint == null ){  
  42.                         connectionManager.rollback(transaction.getConnection());  
  43.                     }else{  
  44.                         connectionManager.rollback(transaction.getConnection(), savepoint);  
  45.                     }  
  46.                 }else{  
  47.                     connectionManager.rollback(transaction.getConnection());  
  48.                 }  
  49.             }  
  50.         }catch( Exception e2){  
  51.             throw new TransactionException();  
  52.         }  
  53.     }  
  54.       
  55.     public void closeTransaction(Transaction transaction){  
  56.         try{  
  57.             if( transaction.isNewTransaction() ){  
  58.                 this.transactions.remove();  
  59.                 connectionManager.setTransactionActive(false);  
  60.                 connectionManager.releaseConnection(transaction.getConnection());  
  61.             }else{  
  62.                 transaction.completeService();  
  63.             }  
  64.         }catch(Exception e){  
  65.             throw new TransactionException();  
  66.         }  
  67.           
  68.           
  69.     }  
  70.       
  71.     /** 
  72.      * @return 
  73.      * @throws ClassNotFoundException 
  74.      * @throws SQLException 
  75.      */  
  76.       
  77.   
  78.     /** 
  79.      * @return the connectionManager 
  80.      */  
  81.     public ConnectionManager getConnectionManager() {  
  82.         return connectionManager;  
  83.     }  
  84.   
  85.     /** 
  86.      * @param connectionManager the connectionManager to set 
  87.      */  
  88.     public void setConnectionManager(ConnectionManager connectionManager) {  
  89.         this.connectionManager = connectionManager;  
  90.     }  
  91.       
  92.       
  93.     public void addSavePoint(String savePointName, Exception rollbackException){  
  94.         Transaction tr = this.transactions.get();  
  95.         if(tr == null){  
  96.             tr = this.beginTransaction();  
  97.         }  
  98.         try{  
  99.             if(!tr.isSupportSavepoint()){  
  100.                 throw new SavePointNotSupportException();  
  101.             }  
  102.             tr.addSavepointAndRollbackException(savePointName, rollbackException);  
  103.         }catch(Exception e){  
  104.             throw new TransactionException();  
  105.         }  
  106.     }  
  107.       
  108.   
  109. }  


5. ConnectionManager对象的实现
Java代码   收藏代码
  1. public class ConnectionManager {  
  2.       
  3.     private static ConnectionManager connectionManager = new ConnectionManager();  
  4.       
  5.     ThreadLocal<Connection> threadConnection = new ThreadLocal<Connection>();  
  6.       
  7.     private ConnectionManager(){}  
  8.       
  9.     public static ConnectionManager getConnectionManager(){  
  10.   
  11.         return connectionManager;  
  12.     }  
  13.       
  14.     private Boolean isTransactionActive = Boolean.FALSE;  
  15.       
  16.     public Connection getConnection() throws ClassNotFoundException, SQLException{  
  17.         Connection connection = this.threadConnection.get();  
  18.         if( connection == null ){  
  19.             connection = (Connection) DriverManager.getConnection (  
  20.                     "jdbc:sqlserver://10.171.30.11:1433;instanceName=nasa;databaseName=nasa2_SMS_PT;SelectMethod=cursor;characterEncoding=utf-8;autoReconnectForPools=true;autoReconnect=true",   
  21.                     "sms""sms");  
  22.             this.threadConnection.set(connection);  
  23.         }  
  24.         return connection;  
  25.     }  
  26.       
  27.     public void releaseConnection(Connection connection) throws SQLException{  
  28.         if( !isTransactionActive ){  
  29.             threadConnection.remove();  
  30.             connection.close();  
  31.         }  
  32.           
  33.     }  
  34.       
  35.     public void commit(Connection connection) throws SQLException{  
  36.         if( !isTransactionActive ){  
  37.             connection.commit();  
  38.         }  
  39.     }  
  40.       
  41.     public void rollback(Connection connection) throws SQLException{  
  42.         if( !isTransactionActive ){  
  43.             connection.rollback();  
  44.         }  
  45.     }  
  46.       
  47.     public void rollback(Connection connection, Savepoint savepoint) throws SQLException{  
  48.         if( !isTransactionActive ){  
  49.             connection.rollback(savepoint);  
  50.         }  
  51.     }  
  52.       
  53.   
  54.     /** 
  55.      * @param isTransactionFinished the isTransactionFinished to set 
  56.      */  
  57.     public void setTransactionActive(Boolean isTransactionActive) {  
  58.         this.isTransactionActive = isTransactionActive;  
  59.     }  
  60.       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值