Mybatis源码解析 —— Sql解析详解

  • 引言
  • Sql解析架构
    • 从注解xml 定义到MappedStatement
    • 从MappedStatement到可执行的Sql
  • 结语

引言

在Java Server理解与实践 ——Spring集成Mybatis中,笔者简要地介绍了Mybatis框架。

Mybatis框架极大地简化了ORM,让使用者自定义sql语句,再将查询结果映射到Java类中,其中很关键的一部分就是,将用户写的sql语句(以xml或者注解形式)解析成数据库可执行的sql语句。

本文将会介绍这整个的解析过程。

Sql解析架构

本文将以一下的注解定义为例,剖析整个解析过程。

@Select({""})
    List selectAccountsByIds(@Param("list") int[] ids);

Sql解析其实分成了两部分,第一部分是将注解/xml中定义的sql语句转化成内存中的MappedStatement,也就是将script部分转化成内存中的MappedStatement,这部分发生在Mybatis初始化的时候,第二部分则是根据MappedStatement以及传入的参数,生成可以直接执行的sql语句,这部分发生在mapper函数被调用的时候。

从注解/xml 定义到MappedStatement

首先,我们要明白什么是MappedStatement,先来看看MappedStatment的类定义。

public final class MappedStatement {

  private String resource; //来源,一般为文件名或者是注解的类名
  private Configuration configuration; //Mybatis的全局唯一Configuration
  private String id; //标志符,可以用于缓存
  private Integer fetchSize; //每次需要查询的行数(可选)
  private Integer timeout;//超时时间
  private StatementType statementType;//语句类型,决定最后将使用Statement, PreparedStatement还是CallableStatement进行查询
  private ResultSetType resultSetType;//结果集的读取类型,与java.sql.ResultSet中的类型对应。
  private SqlSource sqlSource;//Mybatis中的sqlSource,保存了初次解析的结果
  private Cache cache;//缓存空间
  private ParameterMap parameterMap;//保存了方法参数与sql语句中的参数对应关系
  private List resultMaps;//可选,定义结果集与Java类型中的字段映射关系
  private boolean flushCacheRequired;//是否立即写入
  private boolean useCache;//是否使用缓存
  private boolean resultOrdered;//可选,默认为false
  private SqlCommandType sqlCommandType;//Sql执行类型(增、删、改、查)
  private KeyGenerator keyGenerator;//可选,键生成器
  private String[] keyProperties;//可选,作为键的属性
  private String[] keyColumns;//可选,键的列
  private boolean hasNestedResultMaps;//是否有嵌套的映射关系
  private String databaseId;//数据库的id
  private Log statementLog;//logger
  private LanguageDriver lang;//解析器
  private String[] resultSets;//可选,数据集的名称
 }

可以说,MappedStatement里面包含了Mybatis有关Sql执行的所有特性,在这里我们能够找到Mybatis在Sql执行层面支持哪些特性,比如说可以支持定制化的数据库列到Java属性的映射,定制化的主键生成器。

对MappedStatement有一定的了解之后,我们就可以接着看整个的处理流程了。

处理流程如下图所示:

Mybatis源码解析 —— Sql解析详解_第1张图片

在这里,我们能够看到清晰的分层结构,从Configuration到具体的NodeHandlers,其实解析的任务一层层分解下来了。另外,最后解析生成的MappedStatement也会注册到Configuration中,保证了Configuration持有对所有MappedStatement的引用。

接下来,我们看一些具体的处理逻辑,也是比较有意思的部分。

XMLLanguageDriver

@Override
  public SqlSource createSqlSource(Configuration configuration, String script, Class parameterType) {
    // issue #3
    if (script.startsWith("
                    
                    

你可能感兴趣的:(JavaServer)