标签: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