Mybatis精讲(二)---生命周期

回顾

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

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

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.这过程当中哪些是全局的。哪些又适合作成复用的。

加入战队数据库

# 加入战队

微信公众号

微信公众号

相关文章
相关标签/搜索