之前我们分析了Mybatis初始做的工作,以及Mapper执行命令的部分原理,接下来我们就准备开始Mybatis到底是如何去分析执行SQL的。而这个过程十分依赖MappedStatement这个类,所以我们继续分析之前先把这个类简单介绍一下,它主要是Mybatis初始化时通过解析mapper对应的XML文件来生成,它的每个属性基本上都能对上XML中的某一个配置。
demo
<select id="count" resultType="int">
SELECT
count(1)
FROM
<include refid="table"/>
</select>
<select id="queryPage" parameterType="cn.com.bsfit.model.so.EmployeeSO" resultMap="baseResultMap">
SELECT
<include refid="base_columns"/>
FROM
<include refid="table"/>
limit #{offset},#{limit}
</select>
MappedStatement 字段解析
public final class MappedStatement {
// Mapper来源,当前Statement是哪个XML文件解析出来的。
// 例如:file [/home/hwb/git/study/studymybatis/target/classes/cn/com/bsfit/mapper/PersonMapper.xml]
private String resource;
// 全局的配置
private Configuration configuration;
// sql id , 如例子中的 count
private String id;
// fetchSize, ResultSet.next()取数据时客户端缓存行数大小
private Integer fetchSize;
// sql超时时间
private Integer timeout;
// sql的类型,INSERT | DELETE | UPDATE | SELECT
private StatementType statementType;
// ResultSet的ResultSetType
private ResultSetType resultSetType;
// 解析了mybatis语法后带占位符的Sql,例如: SELECT id, userId, userName, nickName, gender, mobilePhone, miliao, email FROM employee limit ?,?
private SqlSource sqlSource;
// mybatis 2级缓存
private Cache cache;
// 请求参数类型
private ParameterMap parameterMap;
// 返回结果类型
private List<ResultMap> resultMaps;
// 是否需要刷新缓存
private boolean flushCacheRequired;
// 是否使用缓存
private boolean useCache;
// 这个设置仅针对嵌套结果 select 语句适用:如果为 true,就是假设包含了嵌套结果集或是分组了,这样的话当返回一个主结果行的时候,就不会发生有对前面结果集的引用的情况。这就使得在获取嵌套的结果集的时候不至于导致内存不够用。默认值:false。
private boolean resultOrdered;
// SQL类型 UNKNOWN, INSERT, UPDATE, DELETE, SELECT;
private SqlCommandType sqlCommandType;
// 主键生成器
private KeyGenerator keyGenerator;
// 对应XML中的keyProperty selectKey 语句结果应该被设置的目标属性。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
private String[] keyProperties;
// keyColumn 匹配属性的返回结果集中的列名称。如果希望得到多个生成的列,也可以是逗号分隔的属性名称列表。
private String[] keyColumns;
// 对应的ResultMap对用有内置的ResultMap
private boolean hasNestedResultMaps;
// 如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有的不带 databaseId 或匹配当前 databaseId 的语句;如果带或者不带的语句都有,则不带的会被忽略。
// 在使用多个数据库的情况下使用
private String databaseId;
// 内部日志类
private Log statementLog;
// 默认是XMLLanguageDriver
private LanguageDriver lang;
// 这个设置仅对多结果集的情况适用。它将列出语句执行后返回的结果集并给每个结果集一个名称,名称是逗号分隔的
private String[] resultSets;
}
简单介绍一下它的解析逻辑
首先是在SqlSessionFactoryBean中创建SqlSessionFactory时,通过把配置好的XML资源路径传递给XMLMapperBuilder,由XMLMapperBuilder去解析XML,然后再交由XMLStatementBuilder类去具体解析某一个SQL对应的配置,最后由MapperBuilderAssistant帮忙注册到configuration中的Map<String, MappedStatement> mappedStatements中。
下面的图片是Mybatis各种Builder类,它们都继承了BaseBuilder,有兴趣的同学可以自行了解下。
Builder.png
ok,今天到这里了,接下来就要开始分析Mybaits是如何执行SQL的了。
网友评论