美文网首页
Mybatis运行原理02-构建sqlSession

Mybatis运行原理02-构建sqlSession

作者: 布拉德老瓜 | 来源:发表于2021-03-07 00:29 被阅读0次

    在上一篇文章中,解析了SqlSessionFactory的创建过程:读取配置文件-->解析配置-->创建Configuration对象-->将mybatis配置属性、mapper等信息封装到Configuration对象内-->以configuration作为参数创建sqlSessionFactory。

    在本文中,将讲述SqlSession的结构、作用以及创建过程。在 MyBatis 中,SqlSession 是一个重要接口,它相当于一个门面,起着连接应用与底层执行器executor的作用。通过它,用户可以来实现对数据的操作、事务的控制和mapper代理对象的获取。在 MyBatis 中有两个SqlSession实现类,DefaultSqlSession 和 SqlSessionManager。本文重点讲DefaultSqlSession,并将捎带一点SqlSessionManager。

    1.SqlSession的创建过程

        public SqlSession openSession() {
            return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
        }
    
    /**
    *      参数:execType:"SIMPLE", level: null, autoCommit: false
    */
        private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
            Transaction tx = null;
    
            DefaultSqlSession var8;
            try {
                Environment environment = this.configuration.getEnvironment();
                TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
                tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
                Executor executor = this.configuration.newExecutor(tx, execType);
                var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
            } catch (Exception var12) {
                this.closeTransaction(tx);
                throw ExceptionFactory.wrapException("Error opening session.  Cause: " + var12, var12);
            } finally {
                ErrorContext.instance().reset();
            }
    
            return var8;
        }
    

    openSessionFromDataSource在创建SqlSession过程中做了3件事情:创建事务, 创建执行器, 创建sqlSession。每一步的结果都作为下一步的参数,最终构建出一个可用来表示会话的sqlSession。事实上,sqlSession对象既不直接管理数据库的连接,也不直接操作数据,而是将功能交给了执行器--执行器负责doQuery,同时通过内部封装的tx对象来管理数据库连接和事务的提交/回滚。

    1. 创建事务工厂,用于创建事务,进行事务控制。做法很简单,若在配置文件中对environment配置了事务工厂,那么就从configuration的environment属性中获取transactionFactory,没有则新建一个ManagedTransactionFactory对象。然后由该工厂对象创建事务。
      TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);          
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    

    在mybatis中,事务的作用:获取连接、提交、回滚、关闭连接。

    public interface Transaction {
        Connection getConnection() throws SQLException;
    
        void commit() throws SQLException;
    
        void rollback() throws SQLException;
    
        void close() throws SQLException;
    
        Integer getTimeout() throws SQLException;
    }
    
    1. 创建执行器Executor


      Executor创建过程

      Executor有3种类型: Simple, Reuse, Batch.
      //todo:区别与共性

    2.1 SimpleExecutor的创建
    直接调用了父类BaseExecutor的构造方法。


    SimpleExecutor的创建

    2.2 创建成功之后,若启用了缓存,那么创建一个CachingExecutor并用其包装SimpleExecutor对象。
    2.3 拦截器链为executor植入插件,使用插件完成对executor的代理。简单来说就是采用责任链模式,一层层的创建代理对象,最后返回终极版的executor代理对象。

        public Object pluginAll(Object target) {
            Interceptor interceptor;
            for(Iterator var2 = this.interceptors.iterator(); var2.hasNext(); target = interceptor.plugin(target)) {
                interceptor = (Interceptor)var2.next();
            }
    
            return target;
        }
    
        default Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        public static Object wrap(Object target, Interceptor interceptor) {
            //获取方法签名
            Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
            Class<?> type = target.getClass();
            Class<?>[] interfaces = getAllInterfaces(type, signatureMap);        
            //创建代理对象
            return interfaces.length > 0 ? Proxy.newProxyInstance(type.getClassLoader(), interfaces, new Plugin(target, interceptor, signatureMap)) : target;
        }
    
    1. 创建SqlSession
        public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
            this.configuration = configuration;
            this.executor = executor;
            this.dirty = false;
            this.autoCommit = autoCommit;
        }
    

    还是属性封装,将SqlSessionFactory对象的Configuration、刚创建的executor、autoCommit三个属性封装到sqlSession对象中。

    到这里,sqlSession对象就创建并初始化了。它内部的核心组件就是负责完成与数据库交互的executor和封装配置属性的Configuration。它的作用主要有:通过configuration获取到mapper、通过executor完成crud、事务管理和连接管理。

    相关文章

      网友评论

          本文标题:Mybatis运行原理02-构建sqlSession

          本文链接:https://www.haomeiwen.com/subject/zrzsqltx.html