深入解析ThreadLocal( 五 )


package com.itheima.transfer.utils;import com.mchange.v2.c3p0.ComboPooledDataSource;import java.sql.Connection;import java.sql.SQLException;public class JdbcUtils {//ThreadLocal对象 : 将connection绑定在当前线程中private static final ThreadLocal tl = new ThreadLocal();// c3p0 数据库连接池对象属性private static final ComboPooledDataSource ds = new ComboPooledDataSource();// 获取连接public static Connection getConnection() throws SQLException {//取出当前线程绑定的connection对象Connection conn = tl.get();if (conn == null) {//如果没有 , 则从连接池中取出conn = ds.getConnection();//再将connection对象绑定到当前线程中tl.set(conn);}return conn;}//释放资源public static void release(AutoCloseable... ios) {for (AutoCloseable io : ios) {if (io != null) {try {io.close();} catch (Exception e) {e.printStackTrace();}}}}public static void commitAndClose() {try {Connection conn = getConnection();//提交事务conn.commit();//解除绑定tl.remove();//释放连接conn.close();} catch (SQLException e) {e.printStackTrace();}}public static void rollbackAndClose() {try {Connection conn = getConnection();//回滚事务conn.rollback();//解除绑定tl.remove();//释放连接conn.close();} catch (SQLException e) {e.printStackTrace();}}}(2) AccountService类的修改:不需要传递connection对象
package com.itheima.transfer.service;import com.itheima.transfer.dao.AccountDao;import com.itheima.transfer.utils.JdbcUtils;import java.sql.Connection;public class AccountService {public boolean transfer(String outUser, String inUser, int money) {AccountDao ad = new AccountDao();try {Connection conn = JdbcUtils.getConnection();//开启事务conn.setAutoCommit(false);// 转出 : 这里不需要传参了 !ad.out(outUser, money);// 模拟转账过程中的异常//int i = 1 / 0;// 转入ad.in(inUser, money);//事务提交JdbcUtils.commitAndClose();} catch (Exception e) {e.printStackTrace();//事务回滚JdbcUtils.rollbackAndClose();return false;}return true;}}(3) AccountDao类的修改:照常使用
package com.itheima.transfer.dao;import com.itheima.transfer.utils.JdbcUtils;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;public class AccountDao {public void out(String outUser, int money) throws SQLException {String sql = "update account set money = money - ? where name = ?";Connection conn = JdbcUtils.getConnection();PreparedStatement pstm = conn.prepareStatement(sql);pstm.setInt(1,money);pstm.setString(2,outUser);pstm.executeUpdate();//照常使用//JdbcUtils.release(pstm,conn);JdbcUtils.release(pstm);}public void in(String inUser, int money) throws SQLException {String sql = "update account set money = money + ? where name = ?";Connection conn = JdbcUtils.getConnection();PreparedStatement pstm = conn.prepareStatement(sql);pstm.setInt(1,money);pstm.setString(2,inUser);pstm.executeUpdate();//JdbcUtils.release(pstm,conn);JdbcUtils.release(pstm);}}2.3.2 ThreadLocal方案的好处从上述的案例中我们可以看到 ,在一些特定场景下 , ThreadLocal方案有两个突出的优势:

  1. 传递数据 : 保存每个线程绑定的数据 , 在需要的地方可以直接获取, 避免参数直接传递带来的代码耦合问题