三种 SqlSession

三种 SqlSession

SqlSession​ 是一个接口,并且里面包含了许多 CRUD 操作数据库等方法。

SqlSession​​ 它有三个实现类,分别是 SqlSessionManager​​ 、DefaultSqlSession​​ 和 SqlSessionTemplate​​,其中 DefaultSqlSession​​ 它的默认实现类。

DefaultSqlSession 是线程不安全的 Sqlsession 。也就是说 DefaultSqlSession 不能是单例,必须是多例的。

SqlSessionManager​ 和 SqlSessionTemplate​ 是 SqlSession 的代理版,每次新建一个代理对象。姿势都是一样的,但是代理逻辑SqlSessionInterceptor 是不一样的。

代理 DefaultSqlSession 实现复用

在执行 getSqlSession 时,两则都是利用 SessionFactory 工厂创建一个 DefaultSqlSession。然后尽可能复用 DefaultSqlSession,而非多例的每次使用都创建一个 DefaultSqlSession。

java 复制代码
SqlSession session = sessionFactory.openSession(executorType);

不同之处在于复用逻辑,先看 SqlSessionTemplate 的:

  1. SqlSessionTemplate 会将 SqlSession 封装成 SqlSessionHolder,并有利用引用计数法,当 referenceCount>0。表示 SqlSession 还在使用。
  2. 将 sqlSessionHolder 存放到 TransactionSynchronizationManagersynchronizations 中。synchronizations 是一个 set 集合。

相对 SqlSessionTemplate 的,SqlSessionManage 的比较简单一点。

  1. SqlSessionManage 内部有一个线程私有变量 localSqlSession。private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal();
  2. SqlSessionManage 会将 DefaultSqlSession 放入到 ThreadLocal 线程私有的变量 localSqlSession 中
  3. 用的时候先从 localSqlSession 中获取 DefaultSqlSession,如果没有获取到则创建。
SqlSessionManager 的代理逻辑
java 复制代码
private SqlSessionManager(){
    this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(),
    new Class[]{SqlSession.class}, new SqlSessionInterceptor());
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    SqlSession sqlSession = (SqlSession)SqlSessionManager.this.localSqlSession.get();
    if (sqlSession != null) {
       return method.invoke(sqlSession, args);
    } else {
        SqlSession autoSqlSession = SqlSessionManager.this.openSession();
        Object var8;
        try {
            try {
                Object result = method.invoke(autoSqlSession, args);
                autoSqlSession.commit();
                var8 = result;
            } catch (Throwable var20) {
                autoSqlSession.rollback();
                throw ExceptionUtil.unwrapThrowable(var20);
            }
        } catch (Throwable var21) {

        } finally {
            if (autoSqlSession != null) {
                autoSqlSession.close(); 
            }
        }

        return var8;
    }
}
SqlSessionTemplate 的代理逻辑
java 复制代码
private SqlSessionTemplate(){
    this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), 
    new Class[]{SqlSession.class}, new SqlSessionInterceptor());
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, 
                SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);

    Object unwrapped;
    try {
        Object result = method.invoke(sqlSession, args);
        if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
            sqlSession.commit(true);
        }

        unwrapped = result;
    } catch (Throwable var11) {
        unwrapped = ExceptionUtil.unwrapThrowable(var11);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
            SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
            sqlSession = null;
            Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
            if (translated != null) {
                unwrapped = translated;
            }
        }

        throw (Throwable)unwrapped;
    } finally {
        if (sqlSession != null) {
            SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }

    }

    return unwrapped;
}

相关推荐
老毛肚13 小时前
手写mybatis
java·数据库·mybatis
爱学英语的程序员18 小时前
面试官:你了解过哪些数据库?
java·数据库·spring boot·sql·mysql·mybatis
阿杰真不会敲代码21 小时前
Mybatis-plus入门到精通
java·tomcat·mybatis
侠客行03171 天前
Mybatis连接池实现及池化模式
java·mybatis·源码阅读
老毛肚1 天前
MyBatis体系结构与工作原理 上篇
java·mybatis
独断万古他化2 天前
【SSM开发实战:博客系统】(三)核心业务功能开发与安全加密实现
spring boot·spring·mybatis·博客系统·加密
fengxin_rou2 天前
[Redis从零到精通|第四篇]:缓存穿透、雪崩、击穿
java·redis·缓存·mybatis·idea·多线程
老毛肚2 天前
MyBatis插件原理及Spring集成
java·spring·mybatis
马尔代夫哈哈哈2 天前
MyBatis 入门与实战:从配置到CRUD一站式指南
mybatis
Jul1en_3 天前
【MyBatis/plus】核心配置、插件与 MyBatis-Plus 构造器 Wrapper
mybatis