数据库JDBC(事务操作&ThreadLocal)2

事务传递 Connection 参数案例 中,我们必须传递Connection对象,才可以完成整个事务操作。如果不传递参数,是否可以完成? 在 JDK 中给我们提供了⼀个⼯具类: ThreadLocal,此类可以在当前线程中共享数据。 java.lang.ThreadLocal 该类提供了线程局部 (thread-local) 变量,⽤于在当前线程中共享数据。

ThreadLocal类的使用

java.lang.ThreadLocal 该类提供了线程局部 (thread-local) 变量,⽤于在当前线程中共享数据。 ThreadLocal ⼯具类底层就是相当于⼀个 Map key 存放的当前线程, value 存放需要共享的数据。
时间 线程A(已开启) 线程B(已开启)
T1 创建ThreadLocal对象  
T2 调用set(“wensong”)存入值  
T3 调用get()获取值  
T4   调用get()获取值,结果为null

举例:

public class ThreadLocalDemo {
     public static void main(String[] args) {
         ThreadLocal<String> mainThread = new ThreadLocal<>();
         mainThread.set("wensong");
         System.out.println(mainThread.get());//wensong
         new Thread(()->{
             System.out.println(mainThread.get());//null
         }).start();
     }
}

结论:向ThreadLocal对象中添加的数据只能在当前线程下使⽤。

案例:使⽤ThreadLocal完成转账

分析

 

代码实现

工具类

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * 阿⾥巴巴的连接池 Druid ⼯具类
 */

public class DruidUtils {
    /*
     1. 加载 druid.properties 配置⽂件
     2. 创建 Druid 连接池对象
     3. 提供 获得 连接池对象的⽅法
     4. 提供 通过ThreadLocal 从连接池中 获取连接对象Connection的 ⽅法
     */
    public static DataSource ds = null;
    //给定当前线程绑定连接
    private static ThreadLocal<Connection> local = new ThreadLocal<>();

    static {
        try {
            //1.加载druid.properties配置文件
            InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            Properties prop = new Properties();
            prop.load(is);
            //2。创建Druid连接池
            ds = DruidDataSourceFactory.createDataSource(prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     3. 提供 获得 连接池对象的⽅法
     */
    public static DataSource getDataSource() {
        return ds;
    }
     /*
     4. 提供 通过ThreadLocal 从连接池中 获取连接对象Connection的 ⽅法
     步骤:
     1.从ThreadLocal获得连接
     2.如果没有, 从连接池获得连接, 并保存到ThreadLocal中
     3.获得连接,返回即可
     */
     public static Connection getConnection(){
         try{
             //1,从当前线程中,获得已经绑定的连接
             Connection conn = local.get();
             if(conn==null){
                 //2.第一次使用的话,绑定内容-从连接池获取连接
                 conn= ds.getConnection();
                 //3.将连接存在ThreadLocal中
                 local.set(conn);
             }
             return conn;//获取连接
         } catch (SQLException e) {
             //将编译时异常转换运行时,以后开发中运行时异常使用比较多
             throw new RuntimeException(e);
         }
     }
}

⼊⼝程序不变:https://blog.csdn.net/weixin_40959890/article/details/107749459

servise层

import org.apache.commons.dbutils.DbUtils;

import java.sql.Connection;
import java.sql.SQLException;

public class AccountService {
    /**
     * 业务层事务管理转账的⽅法
     */
    public void transfer(String from , String to , double money){
        //调用dao层
        AccountDao accountdao = new AccountDao();
        //DBUtils使用方法
        Connection conn = null;
        try{
            //获取连接
            conn = DruidUtils.getConnection();
            //设置事务不自动提交
            conn.setAutoCommit(false);
            //调用持久层
            accountdao.outMoney(from,money);
            //如果有异常
            //int n = 1/0;
            accountdao.inMoney(to,money);
            //提交事务,并安静的关闭连接
            DbUtils.commitAndCloseQuietly(conn);
        } catch (SQLException e) {
            //出现异常时,回滚事务,并安静关闭连接
            DbUtils.rollbackAndCloseQuietly(conn);
            e.printStackTrace();
        }
    }
}
dao
import org.apache.commons.dbutils.QueryRunner;

import java.sql.Connection;
import java.sql.SQLException;

public class AccountDao {
    /**
     * 付款⽅法
     * @param from 付款⼈
     * @param money ⾦额
     */
    public void outMoney(String from, String to, Double money){
        QueryRunner qr = new QueryRunner();
        try{
            Connection conn = DruidUtils.getConnection();
            String sql = "update account set money= money -? where name =?";
            qr.update(conn,sql,money,from);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    /**
     * 收款⽅法
     * @param to 收款⼈
     * @param money ⾦额
     */
    public void inMoney(String to,double money){
        QueryRunner qr = new QueryRunner();
        try {
            Connection conn = DruidUtils.getConnection();
            String sql= "update account set money = money+? where name=?";
            qr.update(conn,sql,money,to);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_40959890/article/details/107761226
今日推荐