ThreadLocal改造获取SqlSession的工具类【现在基本不用,spring自动封装了该对象】

ThreadLocal介绍

  • 在实际开发中,我们用MyBatis框架获取SqlSession应该是属于Dao层代码,不允许出现在Service层中,如果dao层数据应用到services层,就提高了耦合度,我们需要删除service层对Mybastis依赖(dao层)
  • ThreadLocal是java.lang.ThreadLocal 该类提供了线程局部 (thread-local) 变量,用于在**当前线程中共享数据

回顾线程了解ThreadLocal

  我们知道 进程是资源的分配单位,线程是运行调度单位。任何运行的程序,必定归属于某个线程。不管是main线程/gc线程还是其他线程。
  程序运行的时候就会产生一个线程,线程里面有一个Context上下文,获取线程上下文的方式:Thread.currentThread().getContext();(返回类型ThreadContext)
  在JDK中线程上下文只有使用的时候才会去创建,而创建线程的上下文就是通过ThreadLocal来实现
ThreadLocal是线程上下文context的代理对象,主要是用来存放数据(通过get和set方法),它是底层是一个基于Map键值对形式存储数据的,而ThreadLocal调用set方法存储数据的时候,它的key就是存放它自己(this-当前的线程)。
在这里插入图片描述

ThreadLocal特点

  1. ThreadLocal工具类底层就是一个Map键值对形式,key存放的当前线程(this),value存放需要共享的数据(只能在相同线程间共享数据)。
  2. 使用哪个线程存储的数据,只能通过该线程取出(存放进去数据的线程)
  3. ThreadLocal 是保证了多线程环境下数据的独立性(不同线程之间数据是不共享的,只有同一个线程数据共享)

通过ThreadLocal来装载MyBatis对象的SqlSession实现service和dao层解耦

改造SqlSessionUtils2:

//sqlSession工具类,获取sqlSession
public class SqlSessionUtils2 {
    
    
    private static SqlSessionFactory sqlSessionFactory;
    //static 静态代码,在类加载的时候执行一次,且只执行一次
    static{
    
    
        //1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        //2. 加载mybatis-config.xml配置文件   参数:核心配置文件
        InputStream inputStream = SqlSessionUtils.class.getClassLoader().getResourceAsStream("com/xgf/mybatisdemo/config/mybatis-config.xml");
        //3. 创建SqlSessionFactory对象  加载核心配置文件  参数:输入流
        sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);

    }

    //通过ThreadLocal改造
    //A: 定义一个ThreadLocal集合,本质是Map<Thread,Object> map
    private   static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();//这个key默认是当前线程,value就是传入的参数SqlSession类型

    public static SqlSession getSession() {
    
    

        //查找在当前线程中,是否有对应的SqlSession
        SqlSession sqlSession = threadLocal.get(); //相当于map.get(Thread.currentThread())
        if (sqlSession != null) {
    
    
            //当前线程存在SqlSession直接返回给调用者使用
            return sqlSession;
        } else {
    
    
            //没有就创建一个新的,并且保存在当前线程中
            sqlSession = sqlSessionFactory.openSession();
            //保存
            threadLocal.set(sqlSession);//实际存储的是threadLocal.set(Thread.currentThread(),sqlSession)
            return sqlSession;//返回
        }
    }

    public static void commitAndClose() {
    
    
        //进行修改表操作,需要提交sqlSession才能更新数据库,定义这个方法
        SqlSession sqlSession = threadLocal.get();
        if (sqlSession != null) {
    
    
            sqlSession.commit();//提交
            sqlSession.close();//关闭
            //已经关闭的session不能留在threadLocal中
            //所以要删除
            threadLocal.remove();
        }
    }

    //出现错误,回调
    public static void rollbackAndClose() {
    
    
        SqlSession sqlSession = threadLocal.get();
        if (sqlSession != null) {
    
    
            sqlSession.rollback();//回滚
            sqlSession.close();//释放
            //已经关闭的session不能留在local
            //所以要删除
            threadLocal.remove();
        }
    }

    //通过该方法实现dao和service解耦
    public static <T> T getMapper(Class className) {
    
    
        return (T) getSession().getMapper(className);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40542534/article/details/108875123