zoukankan      html  css  js  c++  java
  • Mybatis精讲(二)---生命周期

    回顾

    • 上一章节我们通过xml和代码的方式实现了Mybatis环境的配置。代码方式只是简单介绍下。我们也知道我们大部分情况使用的是xml方式的配置。在实际开发中我们那样开发显然是不合理的。

    • 上章节提到的组件显示不可能每次执行sql都要重新创建的。这样性能上肯定是过不去的。今天我们就来简单聊聊SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper这些组件的生命周期吧。

    SqlSessionFactoryBuilder

    • 通过观察分析这个类我们就知道既然是Builder模式的类,那他的作用就是构建起(孵化器).换句话说这个类不是那么的重要,因为他唯一的作用就是孵化SqlSessionFactory。在Spring与Mybatis整合的框架中,我相信Spring一定是在构建了SqlSessionFactory之后就将这个类进行回收了。因为后面就不需要了。这里纯属个人猜想。
    
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        return build(parser.parse());
      } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error building SqlSession.", e);
      } finally {
        ErrorContext.instance().reset();
        try {
          inputStream.close();
        } catch (IOException e) {
          // Intentionally ignore. Prefer previous error.
        }
      }
    }
    
    
    • 上面就是我们通过加载xml配置文件的源码。我们不难发现build核心是通过XMLConfigBuilder这个类去负责解析mybatis-config.xml配置文件并生成Configuration对象。

    SqlSessionFactory

    • 看名字就知道是工厂模式。在这里我们可以把他看成数据库连接池。既然是工厂就肯定得有产品。SqlSessionFactory的产物就是SqlSession。SqlSession是与数据库的一次连接。管理数据库的连接的自然就是连接池了。
    • Mybatis中使用的SqlSessionFactory是DefaultSqlSessionFactory 。 以连接池的角度看待我们不难推断出SqlSessionFactory应该是个单例 。SqlSessionFactory对应的是数据库。一个数据库原则上应该对应一个SqlSessionFactory来管理。这点在Spring中正好无缝连接。把SqlSessionFactory交由spring管理。spring默认是单例模式bean.

    openSessionFromDataSource

    • SqlSessionFactory通过openSession方法获取SqlSession.SQLSession实际上可以看做是一次数据库的连接。下面我们通过源码的方式去看看工厂是如何生产SqlSession的。
    <!--定义数据库信息,默认使用development数据库构建环境-->
    <environments default="development">
        <environment id="development">
            <!--jdbc事物管理-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据库连接信息-->
            <dataSource type="POOLED">
                <property name="driver" value="${database.driver}"/>
                <property name="url" value="${database.url}"/>
                <property name="username" value="${database.username}"/>
                <property name="password" value="${database.password}"/>
            </dataSource>
        </environment>
    </environments>
    
    
    
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
      //定义一个事物对象
      Transaction tx = null;
      try {
        //通过配置对象获取事先配置好的环境对象   这里对应了xml中的environments标签  。environments默认develop.所以是develop的environment
        final Environment environment = configuration.getEnvironment();
        //通过环境获取事物。在environment里配置了JDBC类型的事物==JdbcTransactionFactory;如果没有配置则默认采用ManagedTransactionFactory
        final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
        //构建事物对象 , 实际就是属性的赋值
        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        //获取执行器 BatchExecutor、ReuseExecutor、SimpleExecutor , 选择SimpleExecutor
        //因为默认有缓存,这里会用CachingExecutor包裹原始Executor , 之后会加载各种插件
        final Executor executor = configuration.newExecutor(tx, execType);
        //返回DefaultSqlSession。写死
        return new DefaultSqlSession(configuration, executor, autoCommit);
      } catch (Exception e) {
        closeTransaction(tx); // may have fetched a connection so lets call close()
        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
      } finally {
        ErrorContext.instance().reset();
      }
    }
    
    

    Executor

    • Mybatis的数据库执行器。Mybatis提供了一共四中Executor.这里严格意义上应该说是三种 BatchExecutor、ReuseExecutor、SimpleExecutor。还有一个CachingExecutor。这里为什么不把他算上了。因为这个是一个全局的开关。在settings标签的cacheEnabled设置的。说道这个标签大家都知道这个就是二级缓存的开关。所以这里CachingExecutor就不做介绍了。
    • SimpleExecutor是一种常规执行器,每次执行都会创建一个statement,用完后关闭。
    • ReuseExecutor是可重用执行器,将statement存入map中,操作map中的statement而不会重复创建statement。
    • BatchExecutor是批处理型执行器,doUpdate预处理存储过程或批处理操作,doQuery提交并执行过程。
    • 关于Executor的选取也是在settings标签控制的。defaultExecutorType。 默认是simple

    SqlSession

    • 每个线程都有一个属于自己的Sqlsession对象。这里我们看成是一次Connection。他的生命周期应该是一次完成的事物处理过程。他是一个线程不安全的对象。在多线程操作的时候我们需要注意事物的隔离级别。我们操作时需要注意的是每次处理玩需要将他关闭。否则会造成资源浪费。在Mybaits中已经通过finnally把我们将他释放了。

    Mapper

    • Mapper是一个接口,我们可以将xml看成他的一个实现类。这里的实现类虚化。通过Java代码的调用实际将xml对应的sql发送给数据库并获取数据结果。
    
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
      final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
      if (mapperProxyFactory == null) {
        throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
      }
      try {
        return mapperProxyFactory.newInstance(sqlSession);
      } catch (Exception e) {
        throw new BindingException("Error getting mapper instance. Cause: " + e, e);
      }
    }
    
    
    • 通过上述代码我们能够发现。在获取Mapper的时候先通过类型看是否被注册了。然后根据类别获取代理实例。

    总结

    • 关于生命周期其实没什么重点。这一章节也比较简单。我们只需要知道我们最终需要的Mapper。然后是如何从配置到获取Mapper.这过程中哪些是全局的。哪些又适合做成复用的。

    加入战队

    # 加入战队

    微信公众号

    微信公众号

  • 相关阅读:
    HDOJ 1025 Constructing Roads In JGShining&#39;s Kingdom
    HDOJ 1274 展开字符串
    HDOJ 1503 Advanced Fruits
    Codeforces Round #187 (Div. 2) A,B
    HDOJ 1160 FatMouse&#39;s Speed
    HDOJ 1267 下沙的沙子有几粒?
    HDOJ 1224 Free DIY Tour
    山娃向大家问好啦。
    开发系统建议
    打开web全屏
  • 原文地址:https://www.cnblogs.com/zhangxinhua/p/11898350.html
Copyright © 2011-2022 走看看