三种 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;
}

相关推荐
2501_9418008814 小时前
Java高性能搜索引擎与Lucene实战分享:大规模文本索引、检索与优化经验
mybatis
q***428217 小时前
SpringCloud-持久层框架MyBatis Plus的使用与原理详解
spring·spring cloud·mybatis
北郭guo19 小时前
MyBatis框架讲解,工作原理、核心内容、如何实现【从浅入深】让你看完这篇文档对于MyBatis的理解更加深入
java·数据库·mybatis
♡喜欢做梦2 天前
MyBatis XML 配置文件:从配置规范到 CRUD 开发实践
xml·java·java-ee·mybatis
q***69772 天前
Spring Boot与MyBatis
spring boot·后端·mybatis
tanxiaomi2 天前
Spring、Spring MVC 和 Spring Boot ,mybatis 相关面试题
java·开发语言·mybatis
q***96583 天前
Spring Boot 集成 MyBatis 全面讲解
spring boot·后端·mybatis
p***93033 天前
Spring Boot中集成MyBatis操作数据库详细教程
数据库·spring boot·mybatis
chxii3 天前
在 MyBatis 中开启 SQL 日志
java·数据库·mybatis
222you3 天前
MyBatis-Plus当中BaseMapper接口的增删查改操作
java·开发语言·mybatis