`
Rambing
  • 浏览: 31965 次
  • 性别: 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;
	}
	
}

分享到:
评论

相关推荐

    java——jdbc学习总结

    - **数据库供应商提供的JDBC驱动**:由数据库厂商如Oracle、MySQL、SQL Server等实现,提供原生的Java支持。 3. **JDBC API**: - **DriverManager类**:负责管理数据库驱动,加载并注册驱动,以及创建数据库连接...

    jdbc——内嵌事务

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

    基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分(源代码+论文)

    《基于JSP技术的猎头公司管理软件的设计与实现——内部事务部分》 本文主要探讨的是如何运用JSP(JavaServer Pages)技术开发一款适用于猎头公司的管理软件,特别是其内部事务处理模块。JSP是一种动态网页技术,它...

    JDBC事务管理(添加dbcp和c3p0测试.zip

    首先,让我们了解JDBC事务管理。在JDBC中,事务的开始、提交和回滚可以通过Connection对象来控制。`setAutoCommit(false)`会禁用自动提交,这时就需要手动调用`commit()`或`rollback()`来决定事务的最终状态。例如:...

    myBatis系列之七:事务管理

    JDBC事务管理器适用于简单的应用程序,而Spring事务管理器更适合于使用Spring框架的项目,因为它提供了更高级的事务控制和回滚策略。 4. **SqlSessionFactory和SqlSession的角色**:SqlSessionFactory是MyBatis的...

    spring分别与jdbc和hibernate结合的事务控制--案例

    本案例重点探讨了Spring如何与两种流行的数据访问技术——JDBC(Java Database Connectivity)和Hibernate——相结合,进行事务管理。事务控制是确保数据库操作一致性、完整性的关键,尤其在多步骤操作中,它能防止...

    基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分(源代码+论文).zip

    《基于JSP技术的猎头公司管理软件设计与实现——内部事务部分》 本文将深入探讨如何利用Java的JSP(JavaServer Pages)技术来设计并实现一款针对猎头公司的内部事务管理软件。该软件旨在优化猎头公司的日常工作流程...

    jdbc课件——关于JDBC的基础知识

    学习JDBC和MySQL的基础知识,不仅可以帮助你理解和操作数据库,还可以为进一步深入学习数据库设计、SQL优化、事务处理、存储过程等高级主题打下坚实基础。在实际开发中,熟练掌握JDBC能有效提升数据操作的效率和代码...

    基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分(源代码+论文).rar

    《基于JSP技术的猎头公司管理软件设计与实现——内部事务部分》 本文将深入探讨一款基于JSP(JavaServer Pages)技术的猎头公司管理软件的设计与实现,主要关注其内部事务处理部分。JSP是Java平台上的动态网页开发...

    Spring 框架的事务管理及应用

    **示例:传统的JDBC事务管理** 在使用JDBC进行数据操作时,传统的事务管理通常涉及到手动管理`Connection`对象的获取、开启事务、执行SQL、提交或回滚事务等步骤。这种方式不仅代码量大,而且容易出错。 ```java ...

    基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分(源代码+论文)_jsp_java源程序代码.rar

    《基于JSP技术的猎头公司管理软件设计与实现——内部事务部分》 在现代商业环境中,猎头公司扮演着连接企业与人才的关键角色。为了提高业务效率和管理水平,开发一款基于JSP技术的猎头公司管理软件显得尤为重要。本...

    适用SQL Server 2016版本的数据库加载驱动包——sqljdbc42.jar

    5. **事务管理**:使用Connection对象的`setAutoCommit()`和`commit()`方法控制事务的提交和回滚。 6. **连接池**:在大型应用中,使用连接池(如C3P0、HikariCP)可以有效管理和复用数据库连接,提高系统性能。 7. ...

    JDBC总结——事务

    【JDBC事务】 在Java数据库连接(JDBC)中,事务是...总之,理解并熟练掌握JDBC事务管理对于编写健壮的数据库应用程序至关重要。通过控制事务,我们可以确保数据的准确性和一致性,防止并发问题,同时优化系统的性能。

    基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分(源代码+设计说明书).zip

    【标题】中的“基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分”表明,这是一个关于使用JavaServer Pages (JSP) 技术开发的管理软件项目,主要关注的是猎头公司的内部事务处理。JSP是Java平台上的一个...

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

    5、JDBC事务特性及常用方法: - 事务特性包括原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),简称ACID。 - 常用方法: - Connection的setAutoCommit()方法用于开启或...

    关键技术——JSP与JDBC应用详解(电子版)

    《关键技术——JSP与JDBC应用详解》这本书深入探讨了Java服务器页面(JSP)和Java数据库连接(JDBC)这两个在Web开发中至关重要的技术。对于任何希望在Java平台上进行Web应用程序开发的程序员来说,理解和掌握这两项...

    毕业设计基于JSP技术的猎头公司管理软件的设计和实现——内部事务部分(源代码+论文).zip

    《基于JSP技术的猎头公司管理软件设计与实现——内部事务部分》 本文将深入探讨一个毕业设计项目,即采用JavaServer Pages (JSP) 技术开发的猎头公司管理软件,主要关注其内部事务处理部分。JSP是一种在服务器端...

    SpringBoot事务和Spring事务详讲

    在 Spring Boot 应用中,通常只需要简单的配置就可以启用事务管理功能。 ##### 1. 自动配置 Spring Boot 自动配置了许多常用的事务管理器,如 `DataSourceTransactionManager` 和 `JpaTransactionManager`。这意味...

Global site tag (gtag.js) - Google Analytics