标签:var new t 集合 值类型 binding static null blob tle
org.apache.ibatis.mapping.SqlSource ,SQL 来源接口。它代表从 Mapper XML 或方法注解上,读取的一条 SQL 内容。代码如下:
// SqlSource.java
|
SqlSource 有多个实现类,如下图所示:
org.apache.ibatis.builder.SqlSourceBuilder ,继承 BaseBuilder 抽象类,SqlSource 构建器,负责将 SQL 语句中的 #{} 替换成相应的 ? 占位符,并获取该 ? 占位符对应的 org.apache.ibatis.mapping.ParameterMapping 对象。
// SqlSourceBuilder.java
|
parameterProperties 属性是这个值,答案在 《MyBatis 文档 —— Mapper XML 文件 —— 参数(Parameters)》
// SqlSourceBuilder.java
|
<2> 处,创建 GenericTokenParser 对象。注意,传入的参数是 #{ 和 } 对。<1> 处,创建 ParameterMappingTokenHandler 对象。<3> 处,调用 GenericTokenParser#parse(String originalSql) 方法,执行解析。如果匹配到 #{ + } 对后,会调用 ParameterMappingTokenHandler 对应的 #handleToken(String content) 方法。详细解析,见 「3.3 ParameterMappingTokenHandler」 。<4> 处,创建 StaticSqlSource 对象。关于 StaticSqlSource 类,详细解析,见 「4.1 StaticSqlSource」 。ParameterMappingTokenHandler ,实现 TokenHandler 接口,继承 BaseBuilder 抽象类,负责将匹配到的 #{ 和 } 对,替换成相应的 ? 占位符,并获取该 ? 占位符对应的 org.apache.ibatis.mapping.ParameterMapping 对象。
ParameterMappingTokenHandler 是 SqlSourceBuilder 的内部私有静态类。
// SqlSourceBuilder.java
|
// SqlSourceBuilder.java
|
<1> 处,调用 #buildParameterMapping(String content) 方法,构建 ParameterMapping 对象,并添加到 parameterMappings 中。详细解析,见 「3.3.3 buildParameterMapping」 。<2> 处,返回 ? 占位符。#buildParameterMapping(String content) 方法,构建 ParameterMapping 对象。代码如下:
// SqlSourceBuilder.java
|
<1> 处,调用 #parseParameterMapping(String content) 方法,解析成 Map 集合。代码如下:
// SqlSourceBuilder.java
|
org.apache.ibatis.builder.ParameterExpression 类,继承 HashMap 类,负责参数表达式。感兴趣的胖友,可以自己看看。?? 艿艿暂时没细看。content = "#{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}" 的结果如下图:
<2> 处,获得属性的名字和类型。<3> 处,创建 ParameterMapping.Builder 对象。
<3.1> 处,初始化 ParameterMapping.Builder 对象的属性。<3.2> 处,如果 typeHandlerAlias 非空,则获得对应的 TypeHandler 对象,并设置到 ParameterMapping.Builder 对象中。<3.3> 处,创建 ParameterMapping 对象。org.apache.ibatis.builder.StaticSqlSource ,实现 SqlSource 接口,静态的 SqlSource 实现类。代码如下:
// StaticSqlSource.java
|
StaticSqlSource.sql 属性,上面还是可能包括 ? 占位符。#getBoundSql((Object parameterObject) 方法,创建 BoundSql 对象。通过 parameterMappings 和 parameterObject 属性,可以设置 sql 上的每个占位符的值。例如:
下面,我们来看看下图的两段代码,胖友看看是否发现了什么规律:
下面,我们在「4.2」和「4.3」中,看看两者的区别。
org.apache.ibatis.scripting.xmltags.DynamicSqlSource ,实现 SqlSource 接口,动态的 SqlSource 实现类。代码如下:
// DynamicSqlSource.java
|
${} 表达式的 SQL ,所以它是动态的,需要在每次执行 #getBoundSql(Object parameterObject) 方法,根据参数,生成对应的 SQL 。<1> 处,创建 DynamicContext 对象,并执行 DynamicContext#apply(DynamicContext context) 方法,应用 rootSqlNode ,相当于生成动态 SQL 。<2> 处,创建 SqlSourceBuilder 对象,并执行 SqlSourceBuilder#parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) 方法,解析出 SqlSource 对象。注意:
#{} 对,转换成对应的 ? 占位符,并获取该占位符对应的 ParameterMapping 对象。<3> 处,调用 StaticSqlSource#getBoundSql(Object parameterObject) 方法,获得 BoundSql 对象。<4> 处,从 context.bindings 中,添加附加参数到 BoundSql 对象中。为什么要这么做?胖友回看下 《精尽 MyBatis 源码分析 —— SQL 初始化(上)之 SqlNode》 的 「6.7 ChooseSqlNode」 就明白了。<5> 处,返回 BoundSql 对象。org.apache.ibatis.scripting.xmltags.RawSqlSource ,实现 SqlSource 接口,原始的 SqlSource 实现类。代码如下:
// RawSqlSource.java
|
#{} 表达式,或者不使用任何表达式的情况,所以它是静态的,仅需要在构造方法中,直接生成对应的 SQL 。<1> 处,调用 #getSql(Configuration configuration, SqlNode rootSqlNode) 方法,获得 SQL 。<2> 处,创建 SqlSourceBuilder 对象,并执行 SqlSourceBuilder#parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) 方法,解析出 SqlSource 对象。<1> + <2> 了。#getBoundSql(Object parameterObject) 方法中:
<3> 处,调用 StaticSqlSource#getBoundSql(Object parameterObject) 方法,获得 BoundSql 对象。<1> + <2> 了。这样,RawSqlSource 和 DynamicSqlSource 的区别,是不是就清晰了。
org.apache.ibatis.builder.annotation.ProviderSqlSource ,实现 SqlSource 接口,基于方法上的 @ProviderXXX 注解的 SqlSource 实现类。
// ProviderSqlSource.java
|
// ProviderSqlSource.java
|
<1> 处,调用 #createSqlSource(Object parameterObject) 方法,创建 SqlSource 对象。因为它是通过 @ProviderXXX 注解的指定类的指定方法,动态生成 SQL 。所以,从思路上,和 DynamicSqlSource 是有点接近的。详细解析,见 「4.4.3 createSqlSource」 。<2> 处,调用 SqlSource#getBoundSql(Object parameterObject) 方法,获得 BoundSql 对象。#createSqlSource(Object parameterObject) 方法,创建 SqlSource 对象。代码如下:
// ProviderSqlSource.java
|
<1> 处,获得 SQL 。
<1.1> 处,调用 #extractProviderMethodArguments(Object parameterObject) 方法,获得方法参数。代码如下:
// ProviderSqlSource.java
|
* 逻辑比较简单,胖友思考下。
* `<1.2>` 处,调用 `#extractProviderMethodArguments(Map<String, Object> params, String[] argumentNames)` 方法,获得方法参数。代码如下:
// ProviderSqlSource.java
|
* 逻辑比较简单,胖友思考下。 * 上面两个方法,无法理解的胖友,可以看看 `org.apache.ibatis.submitted.sqlprovider.Mapper` 和 `org.apache.ibatis.submitted.sqlprovider.OurSqlBuilder` 类。 * 调用 `#invokeProviderMethod(Object... args)` 方法,执行方法,生成 SQL 。代码如下:
// ProviderSqlSource.java
|
* 反射调用方法。
<2> 处,获得参数类型。<3> 处,调用 #replacePlaceholder(String sql) 方法,替换掉 SQL 上的属性。代码如下:
// ProviderSqlSource.java
|
<4> 处,调用 SqlSourceBuilder#parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) 方法,解析出 SqlSource 对象。org.apache.ibatis.builder.annotation.ProviderContext ,ProviderSqlSource 的上下文。代码如下:
// ProviderContext.java
|
org.apache.ibatis.mapping.BoundSql ,一次可执行的 SQL 封装。代码如下:
// BoundSql.java
|
org.apache.ibatis.mapping.ParameterMapping ,参数映射。代码如下:
// ParameterMapping.java
|
OUT 和 INOUT 是在存储过程中使用的情况。OUT 和 INOUT 是在存储过程中使用的情况,可以看看 《Mybatis调用MySQL存储过程》 。当然,也可以不看,因为很少使用存储过程了。org.apache.ibatis.mapping.ParameterMode ,参数类型。代码如下:
// ParameterMode.java
|
IN 的情况。org.apache.ibatis.executor.parameter.ParameterHandler ,参数处理器接口。代码如下:
// ParameterHandler.java
|
org.apache.ibatis.scripting.default.DefaultParameterHandler ,实现 ParameterHandler 接口,默认 ParameterHandler 实现类。
// DefaultParameterHandler.java
|
#setParameters(PreparedStatement ps) 方法,代码如下:
// DefaultParameterHandler.java
|
<1> 处,遍历 ParameterMapping 数组。<2> 处,获得 ParameterMapping 对象。<3> 处,获得值。有多种情况,胖友可以细看下。<4> 处,获得 typeHandler、jdbcType 属性。<5> 处,调用 TypeHandler#setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) 方法,设置指定位置的 ? 占位符的参数。标签:var new t 集合 值类型 binding static null blob tle
原文地址:https://www.cnblogs.com/siye1989/p/11622232.html