`
Rambing
  • 浏览: 31440 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

事务管理(三)——JDBC事务管理的简单实现

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

对于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;
	}
	
}

分享到:
评论

相关推荐

    jdbc——内嵌事务

    jdbc——内嵌事务 class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt; &lt;property name="dataSource" ref="dataSource"&gt;&lt;/property&gt; ...

    JDBC总结——事务

    文章目录事务一、事务的基本介绍1、概念2、操作3、操作实例4、MySQL数据库中默认自动提交二、事务的四大特征三、事务的隔离级别1、概念2、存在的问题3、隔离级别四、Jdbc事务控制1、概述2、控制事务的API:3、核心...

    每天十道面试题(五)——JDBC数据库编程部分

    4、简述JDBC中的常用的类和接口5、JDBC事务的特性及常用方法6、简述JDBC原理 1、PreparedStatement接口与Statement接口相比,有哪些优势? 1)性能方面,PreparedStatement有预编译过程,一旦绑定SQL语句就可以执行...

    JDBC专题(五)-JDBC专题-JDBC事务.docx

    3.JDBC中使用事务 3.1.JDBC使用事务范例 3.2设置事务回滚点 1.事务(Transaction)的概念 事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。 举例:需求:把大象放入冰箱 1....

    springboot2+两种方式:(读写分离、动态DataSource、事务懒处理)+sharding-jdbc.zip

    ———————————————— 版权声明:本文为CSDN博主「毛豆有毛没豆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:...

    jdbcDemo.zip

    [Java基础——jdbc],学习jdbc过程中的代码Demo,方便回顾。包括jdbc的简单使用,自定义工具类,批处理,事务管理。

    Java Web程序设计教程

    9.5项目实战——客户订单管理 202 本章小结 207 课后练习 207 第10章hibernate性能优化 208 10.1hibernate事务与并发 208 10.1.1什么是事务 208 10.1.2hibernate中的事务处理 209 10.1.3在hibernate中使用jta...

    Java数据库编程宝典2

    1.3 事务管理和事务控制命令 1.3.1 ACID测试 1.3.2 SQL中的事务管理 1.4 数据库安全和数据控制语言 1.4.1 管理数据库用户 1.4.2 用户权限 1.4.3 用户组和角色 1.5 数据库体系结构 1.5.1 Java数据对象 ...

    Java数据库编程宝典4

    1.3 事务管理和事务控制命令 1.3.1 ACID测试 1.3.2 SQL中的事务管理 1.4 数据库安全和数据控制语言 1.4.1 管理数据库用户 1.4.2 用户权限 1.4.3 用户组和角色 1.5 数据库体系结构 1.5.1 Java数据对象 ...

    Java数据库编程宝典1

    1.3 事务管理和事务控制命令 1.3.1 ACID测试 1.3.2 SQL中的事务管理 1.4 数据库安全和数据控制语言 1.4.1 管理数据库用户 1.4.2 用户权限 1.4.3 用户组和角色 1.5 数据库体系结构 1.5.1 Java数据对象 ...

    Java数据库编程宝典3

    1.3 事务管理和事务控制命令 1.3.1 ACID测试 1.3.2 SQL中的事务管理 1.4 数据库安全和数据控制语言 1.4.1 管理数据库用户 1.4.2 用户权限 1.4.3 用户组和角色 1.5 数据库体系结构 1.5.1 Java数据对象 ...

    Java项目源码经典实用——提高必备【必学必看】

    Java项目源码经典实用——提高必备【必学必看】 各种流行技术和框架应有尽有,部分目录如下。。。。。 Java的UI皮肤 Quaqua.zip Java神经网络框架 Encog for Java.zip Java程序监控API Java Simon.zip Java算术...

    atomikos3.7.0

    提供事务管理和连接池不需要应用服务器 —— TransactionEssentials可以在任何Java EE应用服务器中运行,也就是不依赖于任何应用服务器开源 —— TransactionEssentials是遵守Apache版本2许可的开源软件专注于JDBC/...

    低清版 大型门户网站是这样炼成的.pdf

    6.4 “桃园三结义”——ssh 2组合开发框架始成 404 6.4.1 spring 2.5集成orm中间件hibernate 3.2 404 6.4.2 spring 2.5集成mvc框架struts 2 411 6.4.3 ssh 2组合框架的基本开发步骤—eportal启程 414 6.5 小结 ...

    Spring.3.x企业应用开发实战(完整版).part2

    10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...

    Spring3.x企业应用开发实战(完整版) part1

    10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...

    Spring In Action中文 第三部分

    ·声明式事务与事务管理; ·与其他Web框架集成:Struts、WebWork、Tapestry、Velocity; ·访问J2EE服务,如JMS和EJB; ·使用AOP解决交叉问题; ·企业组应用系统最佳实践。 “……一种解释Spring中各个主题的很好...

    neo4j-jdbc:图数据库

    Neo是一个网络——面向网络的数据库——也就是说,它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络上而不是表中。 网络(从数学角度叫做图)是一个灵活的数据结构...

    hbase phoenix sql

    在Apache HBase上执行SQL查询。 根据项目创建者所述,对于10M到100M的行的简单查询来说,Phoenix要胜过... 通过客户端的批处理实现的有限的事务支持 单表——还没有连接,同时二级索引也在开发当中 紧跟ANSI SQL标准

Global site tag (gtag.js) - Google Analytics