MyBatis构建SqlSessionFactory过程

MyBatis运行过程大致分为两步:

1. 利用XMLConfigBuilder类读取配置文件缓存到Configuration对象(单例),用来创建SqlSessionFactory对象

2. SqlSession的执行过程

 

构建SqlSessionFactory过程:

1. 通过org.apache.ibatis.builder.xml.XMLConfigBuilder解析MyBatis的配置文件,将解析的内容存入Configuration对象(单例)中。

2. 使用Configuration对象,通过SqlSessionFactoryBuilder去创建SqlSessionFactory对象,这里采用的事建造者(Builder)模式。MyBatis中的SqlSessionFactory是一个接口,它有一个默认的实现类DefaultSqlSessionFactory。通常情况下使用这个类就够了。

 

解析配置文件的源码:

       MyBatis构建SqlSessionFactory过程

 

 

Configuration的作用:

1. 存放配置信息,包括基础配置的XML和映射器XML(或注解)

2. 初始化一些配置,如类型别名,一些重要的对象(插件、映射器、Object工厂、typeHandlers对象等)

3. 提供单例,为后续创建SessionFactory服务,提供配置参数等。

4. 执行一些重要的初始化方法

它会做如下初始化:

  • properties参数
  • typeAliases别名
  • Plugins插件
  • objectFactory工厂
  • reflectionFactory反射工厂
  • settings环境设置
  • environments数据库环境
  • databaseIdProvider数据库标识
  • typeHandlers类型转换器
  • Mappers映射器

 

构建映射器的内部组成:

当XMLConfigBuilder解析XML时,会将每一个SQL和其配置的内容保存起来。一般而言,一条SQL和它相关的配置信息是由3个部分组成,分别是MappedStatement、SqlSource和BoundSql。

  • MappedStatement的作用是保存一个映射器节点(select | insert | update | delete)的内容。它是一个类,包括许多我们配置的SQL、SQL的id、缓存信息、resultMap、parameterType、resultType、languageDriver等重要配置内容。还有一个重要的属性就是sqlSource。MyBatis通过读取它来获取某条SQL配置的所有信息。

       MyBatis构建SqlSessionFactory过程

 

  • SqlSource是提供BoundSql对象的地方,它是MappedStatement的一个属性,并且它是一个接口,而不是一个实现类。它的几个重要实现类是:DynamicSqlSource、ProviderSqlSource、RawSqlSource、StaticSqlSource。它的作用是根据上下文和参数解析生成需要的SQL。

       MyBatis构建SqlSessionFactory过程

 

  • BoundSql是一个结果对象,也就是SqlSource通过对SQL和参数的联合解析得到的SQL和参数,它是建立SQL和参数的地方,它有三个常用的属性:sql、parameterObject、parameterMappings。MyBatis构建SqlSessionFactory过程

 

MappedStatement对象涉及的内容比较多,一般不去修改它

SqlSource是一个接口,主要作用是根据参数和其他的规则组装SQL,一般也不需要修改。

对于最终的参数和SQL都反映在BoundSql类对象上,在插件中往往需要拿到它进而拿到SQL和参数,从而对运行做出必要的修改,来满足特殊需求,这便是MyBatis插件提供的功能。

 

BoundSql类主要的三个属性是:sql、parameterMapping和parameterObject

(1)parameterObject是查询参数(实际使用中传入的查询条件),可以传递简单对象、POJO或者Map、@Param的注解的参数,在插件中十分常用。

  • 传递简单对象,包括int、String、float、double等。传递int时会自动将参数转变为Integer对象传递,类似的long、float、double也是如此。
  • 传递POJO或Map,parameterObject就是传入的POJO或Map
  • 传递多个参数,如果没有@Param注解,MyBatis会把parameterObject变为一个Map<String, Object>对象,其键值的关系是按顺序来规划的,类似于{“1”:p1, "2":p2, "3":p3......“param1”:p1, "param2":p2, "param3": p3......}这样的形式,所以在编写时可以使用#{param1}或者#{1}这样的形式去引用第一个参数。
  • 使用@Param注解,MyBatis就会把parameterObject也变为一个Map<String, Object>对象,类似于没有@Param注解,只是把其数字的键值置换成@Param注解值,比如注解@Param("key1")String p1, @Param("key2") int p2, @Param("key3")Role p3,那么ParameterObject对象就是一个Map<String, Object>,它的键值包含{“key1”, p1, "key2":p2, "key3":p3, "param1":p1,"param2":p2,"param3":p3}

(2)parameterMappings是一个List,它的每一个元素都是ParameterMapping对象。对象会描述参数,参数包括属性名称、表达式、javaType、jdbcType、typeHandler等重要信息,通过它就可以实现参数和SQL的结合,以便PreparedStatement能够通过它找到parameterObject对象的属性设置参数。

(3)sql属性就是书写在映射器里面的一条被SqlSource解析后的SQL。一般只是再使用插件时根据需要进行改写。