概述:
为了学习事务的管理,实现了如下的一个简单版本的事务管理器,进行实验。该管理器简化了事务管理的各种异常类型的考虑。
对于Transaction 管理
为了实现数据一致性,对于数据库的JDBC编程通常需要在代码中显示的调用Connection方法的事务相关API来完成工作。
常见的代码如下:
在以上的代码中与业务逻辑相关的代码只有一行, 为了简化事务的操作,实现一个简单的事务管理控制。主要提供以下方面的统一控制。
1.使用回调机制简化事务处理的代码
2.增加对事务隔离级别的支持
3.增加事务Timeout的管理,最简单的实现。 尽早发现长事务的操作。
4.对于savepoint的支持
5.实现一种事务传播控制。 如果当前存在事务,就加入该事务中执行,如果没有新建事务,放到事务中实现。
实现了该事务控制管理器后,将Service的代码得到如下的简化:
1. 回调的实现
定义模板类TransactionTemplate
其主要的方法就是提供模板方法对事务处理的代码进行控制:
2. 回调接口的定义非常的简单:
3. 重点Transaction类的实现,管理了Connection对象,事务隔离级别的定义,事务的savepoint控制点,以及对于事务状态的控制。
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对象,并且控制着事务的操作。
其代码如下
5. ConnectionManager对象的实现
为了学习事务的管理,实现了如下的一个简单版本的事务管理器,进行实验。该管理器简化了事务管理的各种异常类型的考虑。
对于Transaction 管理
为了实现数据一致性,对于数据库的JDBC编程通常需要在代码中显示的调用Connection方法的事务相关API来完成工作。
常见的代码如下:
- public void doService(){
- Connection connection = getConnection();
- connection.setTransactionIsolation(
- Connection.TRANSACTION_READ_COMMITTED);
- try{
- doBusinessLogic(connection);
- connection.commit();
- }catch(Exception e){
- connection.rollback();
- }finally{
- connection.close();
- }
- }
在以上的代码中与业务逻辑相关的代码只有一行, 为了简化事务的操作,实现一个简单的事务管理控制。主要提供以下方面的统一控制。
1.使用回调机制简化事务处理的代码
2.增加对事务隔离级别的支持
3.增加事务Timeout的管理,最简单的实现。 尽早发现长事务的操作。
4.对于savepoint的支持
5.实现一种事务传播控制。 如果当前存在事务,就加入该事务中执行,如果没有新建事务,放到事务中实现。
实现了该事务控制管理器后,将Service的代码得到如下的简化:
- private Service service;
- private Dao dao;
- private TransactionTemplate transactionTemplate;
- public void service(final Object obj) {
- this.trTemplate.executeTransaction(new TransactionCallback(){
- public Object doTransactionEvent() {
- service.doService();
- transactionTemplate.addSavePoint("savepoint1", exception1);
- dao.saveMethod1(obj);
- transactionTemplate.addSavePoint("savepoint2", exception2);
- dao.saveMethod2(obj);
- }
- });
- }
1. 回调的实现
定义模板类TransactionTemplate
其主要的方法就是提供模板方法对事务处理的代码进行控制:
- public class TransactionTemplate {
- private TransactionManager trManager;
- //the timeout monitor is used to find out all long time transaction in advance.
- private boolean useTimeoutMonitor = Boolean.TRUE;
- private Long maxTime = Long.valueOf(2);
- public void addSavePoint(String savePointName, Exception rollbackException){
- this.trManager.addSavePoint(savePointName, rollbackException);
- }
- public void executeTransaction(
- TransactionCallback transactionCallback, int isolationLevel) {
- long startTime = System.currentTimeMillis();
- Transaction transaction = null;
- try{
- transaction = trManager.beginTransaction();
- checkTimeout(startTime);
- transaction.setTransactionIsolationLevel(isolationLevel);
- transactionCallback.doTransactionEvent();
- checkTimeout(startTime);
- trManager.commitTransaction(transaction);
- }catch(Exception e){
- trManager.rollbackTransaction(transaction, e);
- }finally{
- trManager.closeTransaction(transaction);
- }
- }
- /**
- * If the transaction is timeout throw a transaction time out exception.
- */
- private void checkTimeout(long startTime) {
- if( this.useTimeoutMonitor ){
- if(isTimeout(startTime)){
- throw new TransactionTimeoutException();
- }
- }
- }
- private boolean isTimeout(long startTime) {
- return System.currentTimeMillis() - startTime > this.maxTime ;
- }
- public void executeTransaction(TransactionCallback transactionCallback){
- this.executeTransaction(transactionCallback, Transaction.DEFAULT_ISOLATION_LEVEL);
- }
- public Long getMaxTime() {
- return maxTime;
- }
- public void setMaxTime(Long maxTime) {
- this.maxTime = maxTime;
- }
- }
2. 回调接口的定义非常的简单:
- public interface TransactionCallback {
- public Object doTransactionEvent();
- }
3. 重点Transaction类的实现,管理了Connection对象,事务隔离级别的定义,事务的savepoint控制点,以及对于事务状态的控制。
- public class Transaction {
- public static final int READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
- public static final int READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
- public static final int REPEATALB_READ = Connection.TRANSACTION_REPEATABLE_READ;
- public static final int SERIALIZE = Connection.TRANSACTION_SERIALIZABLE;
- public static final int DEFAULT_ISOLATION_LEVEL = READ_COMMITTED;
- private Map<Exception,Savepoint> savePoints = new HashMap<Exception, Savepoint>();
- //This count is used to implement the transaction propagation
- private int newTrCount = 1;
- Connection connection;
- public Transaction(Connection connection){
- this.connection = connection;
- }
- public void addNewService(){
- this.newTrCount++;
- }
- public void completeService(){
- this.newTrCount--;
- }
- public boolean isNewTransaction(){
- return this.newTrCount == 1;
- }
- /**
- * @return the connection
- */
- public Connection getConnection() {
- return connection;
- }
- /**
- * @param connection the connection to set
- */
- public void setConnection(Connection connection) {
- this.connection = connection;
- }
- /**
- * @param transactionIsolationLevel the transactionIsolationLevel to set
- * @throws SQLException
- */
- public void setTransactionIsolationLevel(int transactionIsolationLevel) throws SQLException {
- this.connection.setAutoCommit(false);
- this.connection.setTransactionIsolation(transactionIsolationLevel);
- }
- public void addSavepointAndRollbackException(String name, Exception e)
- throws SQLException{
- Savepoint savepoint = this.addSavePoint(name);
- this.savePoints.put(e, savepoint);
- }
- public boolean isSupportSavepoint() throws SQLException{
- return this.getConnection().getMetaData().supportsSavepoints();
- }
- private Savepoint addSavePoint(String savepointName) throws SQLException{
- return this.connection.setSavepoint(savepointName);
- }
- public boolean containsSavepoint() {
- return !this.savePoints.isEmpty();
- }
- public Savepoint getSavePointByException(Exception e) {
- return this.savePoints.get(e);
- }
- }
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对象,并且控制着事务的操作。
其代码如下
- public class TransactionManager {
- private ConnectionManager connectionManager;
- private ThreadLocal<Transaction> transactions = new ThreadLocal<Transaction>();
- public Transaction beginTransaction() {
- try{
- Transaction tr = this.transactions.get();
- if( tr == null ){
- Connection connection = connectionManager.getConnection();
- connectionManager.setTransactionActive(true);
- tr = new Transaction(connection);
- this.transactions.set(tr);
- }else{
- tr.addNewService();
- }
- return tr;
- }catch(Exception e){
- throw new TransactionException();
- }
- }
- public void commitTransaction(Transaction transaction) {
- try{
- if( transaction.isNewTransaction() ){
- connectionManager.setTransactionActive(false);
- connectionManager.commit(transaction.getConnection());
- }
- }catch(Exception e){
- throw new TransactionException();
- }
- }
- public void rollbackTransaction(Transaction transaction, Exception e) {
- try{
- if( transaction.isNewTransaction() ){
- connectionManager.setTransactionActive(false);
- if(transaction.containsSavepoint()){
- Savepoint savepoint = transaction.getSavePointByException(e);
- if( savepoint == null ){
- connectionManager.rollback(transaction.getConnection());
- }else{
- connectionManager.rollback(transaction.getConnection(), savepoint);
- }
- }else{
- connectionManager.rollback(transaction.getConnection());
- }
- }
- }catch( Exception e2){
- throw new TransactionException();
- }
- }
- public void closeTransaction(Transaction transaction){
- try{
- if( transaction.isNewTransaction() ){
- this.transactions.remove();
- connectionManager.setTransactionActive(false);
- connectionManager.releaseConnection(transaction.getConnection());
- }else{
- transaction.completeService();
- }
- }catch(Exception e){
- throw new TransactionException();
- }
- }
- /**
- * @return
- * @throws ClassNotFoundException
- * @throws SQLException
- */
- /**
- * @return the connectionManager
- */
- public ConnectionManager getConnectionManager() {
- return connectionManager;
- }
- /**
- * @param connectionManager the connectionManager to set
- */
- public void setConnectionManager(ConnectionManager connectionManager) {
- this.connectionManager = connectionManager;
- }
- public void addSavePoint(String savePointName, Exception rollbackException){
- Transaction tr = this.transactions.get();
- if(tr == null){
- tr = this.beginTransaction();
- }
- try{
- if(!tr.isSupportSavepoint()){
- throw new SavePointNotSupportException();
- }
- tr.addSavepointAndRollbackException(savePointName, rollbackException);
- }catch(Exception e){
- throw new TransactionException();
- }
- }
- }
5. ConnectionManager对象的实现
- public class ConnectionManager {
- private static ConnectionManager connectionManager = new ConnectionManager();
- ThreadLocal<Connection> threadConnection = new ThreadLocal<Connection>();
- private ConnectionManager(){}
- public static ConnectionManager getConnectionManager(){
- return connectionManager;
- }
- private Boolean isTransactionActive = Boolean.FALSE;
- public Connection getConnection() throws ClassNotFoundException, SQLException{
- Connection connection = this.threadConnection.get();
- if( connection == null ){
- connection = (Connection) DriverManager.getConnection (
- "jdbc:sqlserver://10.171.30.11:1433;instanceName=nasa;databaseName=nasa2_SMS_PT;SelectMethod=cursor;characterEncoding=utf-8;autoReconnectForPools=true;autoReconnect=true",
- "sms", "sms");
- this.threadConnection.set(connection);
- }
- return connection;
- }
- public void releaseConnection(Connection connection) throws SQLException{
- if( !isTransactionActive ){
- threadConnection.remove();
- connection.close();
- }
- }
- public void commit(Connection connection) throws SQLException{
- if( !isTransactionActive ){
- connection.commit();
- }
- }
- public void rollback(Connection connection) throws SQLException{
- if( !isTransactionActive ){
- connection.rollback();
- }
- }
- public void rollback(Connection connection, Savepoint savepoint) throws SQLException{
- if( !isTransactionActive ){
- connection.rollback(savepoint);
- }
- }
- /**
- * @param isTransactionFinished the isTransactionFinished to set
- */
- public void setTransactionActive(Boolean isTransactionActive) {
- this.isTransactionActive = isTransactionActive;
- }
- }