事务处理中的ThreadLocal的使用

简单的理解ThreadLocal

所谓ThreadLocal,简单一点想,就是一个全局的Map,Map的key是线程对象,value是你要保存的对象
进入某个线程后,就可以从map中取得之前存储的相应线程关联的对象。
NT:ThreadLocal并不是一个Map,但用Map来理解是没有问题的

在事务中使用ThreadLocal

确保所有的sql语句都在同一个开启了事务的链接上执行,这时候就可以使用ThreadLocal来解决这个问题。
解决思路:

代码实现:
//绑定开启了链接的connection到ThreadLocal的JdbcUtils工具类 public class JdbcUtils { private
static ThreadLocal<Connection> tl = new ThreadLocal<Connection>(); //map public
static void startTransaction(){ try{ //得到当前线程上绑定连接开启事务 Connection conn = tl.get
();if(conn==null){ //代表线程上没有绑定连接 conn = ds.getConnection(); //ds 代表数据源, 这里省略他的代码
tl.set(conn); } conn.setAutoCommit(false); }catch (Exception e) { throw new
RuntimeException(e); } }public static void commitTransaction(){ try{ Connection
conn = tl.get(); if(conn!=null){ conn.commit(); } }catch (Exception e) { throw
new RuntimeException(e); } } public static Connection getConnection() throws
SQLException{try{ //得到当前线程上绑定的连接 Connection conn = tl.get(); if(conn==null){
//代表线程上没有绑定连接 conn = ds.getConnection(); tl.set(conn); } return conn; }catch
(Exception e) {throw new RuntimeException(e); } } } //在服务层用上ThreadLocal的事务管理
public void transfer2(int sourceid,int targetid,double money) throws
SQLException{try{ JdbcUtils.startTransaction(); AccountDao dao = new
AccountDao(); Account a = dao.find(sourceid);//select Account b =
dao.find(targetid);//select a.setMoney(a.getMoney()-money);
b.setMoney(b.getMoney()+money); dao.update(a);//update dao.update(b);//update
JdbcUtils.commitTransaction(); }finally{ JdbcUtils.closeConnection(); } } }
//持久层,获取绑定在当前线程上的connection,进行操作 public Account find(int id){ try{ QueryRunner
runner =new QueryRunner(); String sql = "select * from account where id=?";
return (Account) runner.query(JdbcUtils.getConnection(),sql, id, new
BeanHandler(Account.class)); }catch (Exception e) { throw new
RuntimeException(e); } }
使用ThreadLocal应该注意的问题

在上面的代码中将ThreadLocal对象做成了静态
private static ThreadLocal tl = new ThreadLocal(); //map

因此,每次开启一条线程,ThreadLocal都会有一个Connection加进来,所以,我们要记得将这些Connection移除,不然
这个ThreadLocal静态对象会越变越大,最后导致程序挂掉!!!!!!

-> 即,在关闭链接是,把变量移除
public static void closeConnection(){ try{ Connection conn = tl.get(); if
(conn!=null){ conn.close(); } }catch (Exception e) { throw new
RuntimeException(e); }finally{ tl.remove();
//千万注意,解除当前线程上绑定的链接(从threadlocal容器中移除对应当前线程的链接) } }

技术
©2019-2020 Toolsou All rights reserved,
一个名叫“讨火车”的小村子 终于把火车讨来了c++内存 指针越界检测机制_CrtMemBlockHeade错误总结-myBatis plus 分页记一次EventBus内存泄露导致的项目问题服务器价格有什么差异?Android中获取当前正在显示的Activity实例创建数据mysql库流程在Vue中使用Web Worker最优化方法总结:公式解、数值优化、求解思想使用easyPOI导入Excel数据