`
jamesby
  • 浏览: 380885 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

自己实现的TransactionManager

    博客分类:
  • Java
阅读更多
背景:
目前有一个系统,系统已经写好了,但是要不停的添加新的功能,用Struts,
业务逻辑写在Action中,以后可能增加一层Service。
业务处理和持久层没有使用任何框架,目前是用Dao担任业务处理加持久层双重操作,
但是有些业务处理很复杂,固设计了一个事务处理框架,大家帮我看下有没有线程安全的问题,
第一次使用ThreadLocal,请多指教。


Connection Holder 代码

public class ConnectionHolder {
	private Connection connection = null;
	private boolean rollback = false;
	private boolean isreadonly = false;
	
	public boolean isIsreadonly() {
		return isreadonly;
	}

	public void setIsreadonly(boolean isreadonly) {
		this.isreadonly = isreadonly;
	}
	public Connection getConnection() {
		if (null == connection)
			throw new RuntimeException("connection not exist........");
		return connection;
	}

	public void setConnection(Connection connection) {
		this.connection = connection;
	}

	public boolean isRollback() {
		return rollback;
	}

	public void setRollback(boolean rollback) {
		this.rollback = rollback;
	}
}

TransactionManager 代码
public class TransactionManager {
	private static final Log logger = LogFactory
			.getLog(TransactionManager.class);

	private static ThreadLocal _thread = new ThreadLocal();

	private static void safeCloseConnection(Connection con) {
		try {
			if (null != con)
				con.close();
			con = null;
		} catch (Exception e) {
			logger.error("", e);
		}
	}

	public static void begin() {
		begin(false);
	}

	public static void begin(boolean isReadonly) {
		ConnectionHolder holder = null;
		Connection con = null;
		try {
			con = JNDIUtils.getConnection();

			if (!isReadonly) {
				con.setAutoCommit(false);
			}

			holder = new ConnectionHolder();
			holder.setConnection(con);
			holder.setIsreadonly(isReadonly);

			_thread.set(holder);
		} catch (Exception e) {
			safeCloseConnection(con);
			logger.error("", e);
			throw new RuntimeException();
		}
	}

	private static void commit() {
		ConnectionHolder holder = null;
		Connection con = null;
		try {
			holder = getConnectionHolder();
			con = holder.getConnection();
			if (!holder.isRollback() && !holder.isIsreadonly()) {
				con.commit();
				con.setAutoCommit(true);
			}
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			safeCloseConnection(con);
		}
	}

	public static void end() {
		commit();
	}

	public static void rollback() {
		ConnectionHolder holder = null;
		Connection con = null;
		try {
			holder = getConnectionHolder();
			holder.setRollback(true);
			con = holder.getConnection();
			if (holder.isIsreadonly()) {
				throw new RuntimeException("readonly cannot rollback....");
			}
			con.rollback();
			con.setAutoCommit(true);
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			safeCloseConnection(con);
		}
	}

	private static ConnectionHolder getConnectionHolder() {
		ConnectionHolder holder = (ConnectionHolder) _thread.get();
		if (null != holder)
			return holder;
		throw new RuntimeException("connection holder not exist.......");
	}

	public static Connection openConnection() {
		Connection con = getConnectionHolder().getConnection();
		if (null != con)
			return con;
		throw new RuntimeException("connection not exist.......");
	}
}


Action 部分代码

public ActionForward deleteResourceXqzy(ActionMapping mapping,
		ActionForm form, HttpServletRequest request,
		HttpServletResponse response) {
	try {
		TransactionManager.begin(); //事务开始
		/**
			多次DAO代码调用
			业务处理
			多次DAO代码调用
		*/
	} catch (Exception ex) {
		TransactionManager.rollback(); //事务回滚
		//其它操作
	} finally {
		TransactionManager.end(); //事务提交
		//其它操作
	}
	return mapping.findForward("test");
}


DAO 部分代码

public static void deleteResourceZyfb() throws Exception {
	String sql = null;
	PreparedStatement ps = null;
	try {
		Connection con = TransactionManager.openConnection();
		sql = "";
		ps = con.prepareStatment(sql);
		ps.executeUpdate();
	} finally {
		safeCloseStatementOrRs(ps);
	}
}
分享到:
评论
9 楼 icefire 2007-04-12  
有个问题,在end的同时,是否应该ThreadLocal.remove()呢?
8 楼 icefire 2007-04-09  
正在做毕业设计,不想引入Spring,时间不够,学不过来。
就借用下!!

PS:我会保留版权信息的!呵呵!
7 楼 jamesby 2007-02-28  
JAVA_ED 写道

ServiceA(){
   try{
      begin();
      ServiceB();
      .....
   }
}

你可以去参考一下一些OpenSrc Project的TransactionManager如何实现



事务有三个方面要考虑,隔离级别、传递方式和readonly,隔离级别目前默认,传递方式就是楼上说的这个.

这样的情况还没有考虑,如果考虑目前的想法是加入一个计数器,begin 时 count++,rollback 时 如果 count>1 throw exception count--,否则rollback,

commit时如果count>1 count-- 否则commit.

项目现在紧急,没有时间,我考虑的是TransactionManager这个类的接口稳定,至于如何是最合理最优化的实现,以后再说,先弄个Demo类的东西先跑起来.
6 楼 JAVA_ED 2007-02-27  
jamesby 写道
JAVA_ED 写道
jamesby 写道
to JAVA_ED:

什么意思,能否详细说明一下?
不new ConnectionHolder()那用同一个ConnectionHolder?


nested transaction? 所谓ConnectionHolder应该是个Connection Container
如果每次begin都去新开个connection, 那前一次的不是丢失了吗
这样不如把connection直接绑上去


但是我的使用代码是这样的啊,也就是每个Service Method 只使用一个Connection!

public ActionForward methodName(ActionMapping mapping,   
        ActionForm form, HttpServletRequest request,   
        HttpServletResponse response) {   
    try {   
        TransactionManager.begin(); //事务开始   
        /**  
            多次DAO代码调用  
            业务处理  
            多次DAO代码调用  
        */  
    } catch (Exception ex) {   
        TransactionManager.rollback(); //事务回滚   
        //其它操作   
    } finally {   
        TransactionManager.end(); //事务提交   
        //其它操作   
    }   
    return mapping.findForward("test");   
}


第一个版本我是将Connection绑上去的,但是后来多了readonly和rollback两个状态,所以弄了这个Holder的.



ServiceA(){
   try{
      begin();
      ServiceB();
      .....
   }
}

你可以去参考一下一些OpenSrc Project的TransactionManager如何实现

5 楼 jamesby 2007-02-27  
JAVA_ED 写道
jamesby 写道
to JAVA_ED:

什么意思,能否详细说明一下?
不new ConnectionHolder()那用同一个ConnectionHolder?


nested transaction? 所谓ConnectionHolder应该是个Connection Container
如果每次begin都去新开个connection, 那前一次的不是丢失了吗
这样不如把connection直接绑上去


但是我的使用代码是这样的啊,也就是每个Service Method 只使用一个Connection!

public ActionForward methodName(ActionMapping mapping,   
        ActionForm form, HttpServletRequest request,   
        HttpServletResponse response) {   
    try {   
        TransactionManager.begin(); //事务开始   
        /**  
            多次DAO代码调用  
            业务处理  
            多次DAO代码调用  
        */  
    } catch (Exception ex) {   
        TransactionManager.rollback(); //事务回滚   
        //其它操作   
    } finally {   
        TransactionManager.end(); //事务提交   
        //其它操作   
    }   
    return mapping.findForward("test");   
}


第一个版本我是将Connection绑上去的,但是后来多了readonly和rollback两个状态,所以弄了这个Holder的.

4 楼 JAVA_ED 2007-02-27  
jamesby 写道
to JAVA_ED:

什么意思,能否详细说明一下?
不new ConnectionHolder()那用同一个ConnectionHolder?


nested transaction? 所谓ConnectionHolder应该是个Connection Container
如果每次begin都去新开个connection, 那前一次的不是丢失了吗
这样不如把connection直接绑上去
3 楼 jamesby 2007-02-27  
to JAVA_ED:

什么意思,能否详细说明一下?
不new ConnectionHolder()那用同一个ConnectionHolder?
2 楼 JAVA_ED 2007-02-27  
jamesby 写道
如果以上是成熟的,无线程安全性问题,也可以考虑实现一个TransactionTemplate,代码类似下面这个.

TransactionTemplate

public void execute() throws Exception{
    try
    {
        TransactionManager.begin();
        process();
    }catch(Exception ex){
        TransactionManager.rollback();
        throw e;
    }finally{
        TransactionManager.end();
    }
}
abstract protected void process() throws Exception{}


Action 部分代码

public ActionForward deleteResourceXqzy(ActionMapping mapping,   
        ActionForm form, HttpServletRequest request,   
        HttpServletResponse response) {   
    try {   
               new TransactionTemplate() {
				public void process() {
									}
	     }.execute();
    } catch (Exception ex) {   

    }
    return mapping.findForward("test");   
}  


其实Spring已经有了很完善的功能,不过目前不想对老系统使用Spring!还望大家多给意见,哪些设计的不合理,尤其是线程安全性方面的.当然上面的代码并没有对异常体系进行设计!还是比较习惯使用Exception和RuntimeException这两个异常.


你把ConnectionHolder绑到ThreadLocal  然后每次再去new一个ConnectionHolder再绑一次?
1 楼 jamesby 2007-02-23  
如果以上是成熟的,无线程安全性问题,也可以考虑实现一个TransactionTemplate,代码类似下面这个.

TransactionTemplate

public void execute() throws Exception{
    try
    {
        TransactionManager.begin();
        process();
    }catch(Exception ex){
        TransactionManager.rollback();
        throw e;
    }finally{
        TransactionManager.end();
    }
}
abstract protected void process() throws Exception{}


Action 部分代码

public ActionForward deleteResourceXqzy(ActionMapping mapping,   
        ActionForm form, HttpServletRequest request,   
        HttpServletResponse response) {   
    try {   
               new TransactionTemplate() {
				public void process() {
									}
	     }.execute();
    } catch (Exception ex) {   

    }
    return mapping.findForward("test");   
}  


其实Spring已经有了很完善的功能,不过目前不想对老系统使用Spring!还望大家多给意见,哪些设计的不合理,尤其是线程安全性方面的.当然上面的代码并没有对异常体系进行设计!还是比较习惯使用Exception和RuntimeException这两个异常.

相关推荐

    基于java的企业级应用开发:声明式事务管理.ppt

    <tx:annotation-driven transaction-manager="transactionManager"/> 如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该...

    spring五种事务配置demo

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。...

    基于框架的Web开发-基于注解的事务配置.doc

    1 为业务实现类加上@Transactional注解 为AccountServiceImpl加上@Transactional注解。如下: 也可以加在方法定义前面,可以试试。 2 修改applicationContext-tx.xml 在上添加@Transactional注解并不会完成事务切面...

    Spring事务配置的五种方式

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    Spring事务配置5种方式

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问 时,DataSource实际为SessionFactory,TransactionManager的实现为 HibernateTransactionManager。

    Spring事务配置的五种方法

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    torque-runtime-backport:将新功能和修复程序从Apache Torque Runtime 4.0移植到旧版3.3版本中

    要指定TransactionManager界面的替代实现,您可以选择以下选项之一。 否则,将使用默认的TransactionManagerImpl 。配置方式编辑Torque.properties并在下面添加行: torque.transactionManager = package....

    ibatis 开发指南(pdf)

    使用ibatis 提供的ORM 机制,对业务逻辑实现人员而言,面对的是纯粹的Java 对象, 这一层与通过Hibernate 实现ORM 而言基本一致,而对于具体的数据操作,Hibernate 会自动生成SQL 语句,而ibatis 则要求...

    iBATIS实战

    3.6.5 transactionManager元素 60 3.6.6 typeHandler元素 61 3.6.7 sqlMap元素 61 3.7 小结 62 第4章 使用已映射语句 63 4.1 从基础开始 63 4.1.1 创建JavaBean 64 4.1.2 SqlMap API 66 4.1.3 已映射语句的类型 67 ...

    ssh(structs,spring,hibernate)框架中的上传下载

     •DefaultLobHandler:适用于大部分的数据库,如SqlServer,MySQL,对Oracle 10g也适用,但不适用于Oracle 9i(看来Oracle 9i确实是个怪胎,谁叫Oracle 公司自己都说Oracle 9i是一个过渡性的产品呢)。  •...

    fat:基于springboot,zookeeper,redis分布式事务强一致性方案

    脂肪FAT,基于springboot,使用zookeeper,redis,spring异步,spring transactionManager的强一致性分布式事务解决方案框架介绍纯编码方式,强一致性。使用redis / zookeeper作为注册中心,代理事务的执行,使用...

    spring-torque-tx:Apache Torque 与 Spring 事务管理的轻量级集成

    Apache Torque 4.0 引入了新的TransactionManager接口,允许将事务处理委托给 Spring 等外部框架。 SpringTransactionManagerAdapter就是这样一个实现。 一旦检测到在托管数据源上运行 spring 事务,它会自动禁止 ...

    make-delivery:[HyperConnect通行证,起薪为5000万韩元或更高]这是一项向购买者提供送餐服务的服务。

    目标是实现一个功能,该功能不仅要考虑简单的功能实现,还要考虑大容量流量的处理。 目的是基于面向对象的原理和多种理论基础来编写正确的代码。 文档和单元测试具有较高的优先级,并且还通过CI / CD实施了自动化...

    JTA事务源码示例

    Spring+iBatis+JOTM实现JTA事务: 如何处理跨库事物:spring + jtom 的jta事务是个很好的选择. 这个源码示例非常不错,包括所有的源码和jar包,下载后eclipse 或 myeclipse 导入就能用。 里面有详细的说明和注释,...

    Middleware:攀登之路..

    原子操作的实现原理 并发编程的内存模型 多线程的应用 Java中的锁 Java的并发容器 不安全 线程池 执行者 MySQL 数据库 MySQL基本数据类型 MySQL基本命令 SQL MySQL脆弱原理(读,写) InnonDB存储引擎 锁,MVCC ...

    spring-data-projects:测试SpringData整合其他工具的项目

    Spring Data 简介 SpringData提供了针对数据库(包括SQL和NOSQL)的整合方案,对Hibernate JPA、Jedis等工具的api进行高级的封装,为我们提供简单方便地操作接口。...entityManagerFactory、transactionManager

    Activiti6.0教程例子下载

    它主要解决的是“使在多个参与者之间按照某种预定义的规则传递文档、信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现”。(我的理解就是:将部分或者全部的工作流程、逻辑让计算机帮你...

    springmybatis

    <transactionManager type="JDBC"/> 3. 建立与数据库对应的 java class,以及映射文件. 在src_user下建立package:com.yihaomen.mybatis.model ,并在这个 package 下建立 User 类: 程序...

    SSH第7章上机.zip ACCP8.0

    -- 创建事务管理器(spring针对hibernate实现的事务管理的切面类) --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <!-- 事务的通知类型 -...

    三大框架下分页源代码

    三大框架分页的实现: DAO里写法: //查出页面要显示的字段 -----分页代码 页面上的查询全部 public List<TblNews> page(Integer pageno) { // TODO Auto-generated method stub log.debug("find TblNewsclass...

Global site tag (gtag.js) - Google Analytics