ThreadLocal:线程本地变量该类提供了线程局部变量。这些变量不同于它们的普通对应物,因为访问一个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。ThreadLocal 实例通常是类中的私有静态字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。
事务是一种机制、是一种操作序列,它包含了一组数据库操作命令,这组命令要么全部执行,要么全部不执行。因此事务是一个不可分割的工作逻辑单元。在数据库系统上执行并发操作时事务是作为最小的控制单元来使用的。这特别适用于多用户同时操作的数据通信系统。
在业务逻辑中我们要统一管理事务,但是在一个事务中会涉及到多个Dao,不同的DAO取得的是不同的Connection对象,这样就不能实现统一管理事务。
那么怎么才能实现两个或多个DAO用同一个事务来控制,来统一管理事务那?
首先就要解决一个根本问题,我们在一个事务中,不同的DAO取得的是同一个Connection,这个要怎么实现呢。我们想到了TheadLocal.
因为当一个业务逻辑要对多个DAO进行处理的时候,此操作属于同一个线程内。所以,我们希望能把此Connection放在线程内,或者和线程有关联。
在任何一个线程内都可以用ThreadLocal来保存一个变量的copy,这样,如果此对象存在,就可以直接取用。
如果ThreadLocal中放置connection, 保证事务中的DAO类获取的都是同一个connection,这样才保证事务。所以,在同一个线程内,不同的DAO就可以保证取得到的是同一个Connection
这样就实现了,事务的统一管理
ThreadLocal的API如下图:
下面是ThreadLocal对Connection的封装
/* *采用ThreadLocal封装Connection * */ public Class ConnectionManager { //创建一个私有静态的并且是与事务相关联的局部线程变量 private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>; public static Connection getConnection(){ //获得线程变量connectionHolder的值conn Connection conn = connectionHolder.get(); if (conn == null){ //如果连接为空,则创建连接,另一个工具类,创建连接 conn = DbUtil.getConnection(); //将局部变量connectionHolder的值设置为conn connectionHolder.set(conn); } return conn; }
/** * 关闭连接和从线程变量中删除conn */ public static void closeConnection(){ //获得线程变量connectionHolder的值conn Connection conn = connectionHolder.get(); if (conn != null){ try { //关闭连接 conn.close(); //从线程局部变量中移除conn,如果没有移除掉,下次还会用这个已经关闭的连接,就会出错 connectionHolder.remove(); }catch(SQLException e){ e.printStackTrace(); } } }
/** *开启事务,手动开启 */ public static void beginTransaction(Connection conn){ try { //如果连接存在,再设置连接,否则会出错 if (conn != null){ //默认conn是自动提交, if (conn.getAutoCommit()){ //关闭自动提交,即是手动开启事务 conn.setAutoCommit(false); } } }catch(SQLException e){ e.printStackPrince(); } }
/** * 提交事务 */ public static void commitTransaction(Connection conn){ try{ if (conn != null){ if (!conn.getAutoCommit()){ conn.commit(); } } }catch(SQLException e){ e.printStackTrace(); } }
/** * 回滚事务 */ public static void rollbackTransaction(){ try { if (conn != null){ if(!conn.getAutoCommit()){ conn.rollback(); } } }catch(SQLException e){ e.printStackTrace(); } } }
以下是业务逻辑事务管理
//调用业务逻辑事务管理 public void addFlowCard(FlowCard flowCard) Connection conn = null; try { //从ThreadLocal中取得Connection conn = ConnectionManager.getConnection(); //手动控制事务提交 ConnectionManager.beginTransaction(conn); //添加流向单主信息 flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard); //添加流向单明细信息 flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList()); if (!conn.getAutoCommit()) { //提交事务 ConnectionManager.commitTransaction(conn); } }catch(Exception e) { e.printStackTrace(); if (!conn.getAutoCommit()) { //回滚事务 ConnectionManager.rollbackTransaction(conn); } throw new ApplicationException("操作失败!"); }finally { ConnectionManager.closeConnection(); } }