继上篇分析了getById,我们继续分析其他sql语句(多参数,且参数中指定javaType,jdbcType):
<select id="getById" resultMap="cityResultMap">
SELECT * FROM city where id = #{id}
</select>
<select id="getByNameAndCountryCode" resultType="City">
SELECT * FROM city where Name = #{name} and CountryCode = #{cCode,javaType=string,jdbcType=VARCHAR}
</select>
getByNameAndCountryCode和getById相比,SqlSource的构建几乎一样,我们看看解析传参,先看下这个接口:
City getByNameAndCountryCode(@Param(value = "name") String name, @Param(value = "cCode") String countryCode);
参数用@Param注解标识并指定了value,此时在ParamNameResolve中生成的SortedMap为{0,"name";1,"cCode"}(若不用注解,生成的map(jdk>=1.8且setting中userActuaParamName为true):{0,"arg0";1,"arg1"}或者{0,"0";1,"1"},在接口中写的名字被遗忘)生成的param为:
是个Map对象,还加了两个键值对:param1、param2,再看设置参数:
getById走了typeHandlerRegister.hasTypeHandler分支,而现在parameterObject已经是Map对象,就走到else分支,构建MetaObject,并取出propertName(name、cCode,若没有在接口方法加注解,sql语句就只能用#{arg0}或#{0}了)的值。#{}里面加上javaType和jdbcType的作用就是生成ParameterMapping的typeHandler,若没有添加则生成UnKnowTypeHandler单参数和多参数就是这几处不同。那sqlSession.selectList怎么传参数呢?请自己思考下。
MetaObject分析。。。
继续下一个sql(用$标识参数):
<select id="getByName" resultType="City">
SELECT * FROM city where Name like '%${name}%'
</select>
dao方法:
List<City> getByName(@Param(value = "name") String name);
和之前一样的流程就不说了,这个sql在parseDynamicTags时(构建MixedSqlNode),解析TextSqlNode会判断是否为动态sql,(TextSqlNode判断是否是动态就是判断有无"${}"标识),这里就把TextSqlNode加到MixedSqlNode中了。在使用SqlSource时:
处理sql语句中${name},直接用参数(zhou)替换了name:
假如方法没有@Param注解,OgnlCache.getValue就会报错:
看来对于单个参数而言,如果没有使用@Param注解,参数内容会被直接传递,若有@Param,则参数会被构建为ParamMap对象,key为@Param的value值,value为实际参数值。getBoundSql方法继续往下走,最终还是生成了StaticSqlSource。
动态sql就是在执行某个方法时根据实际参数把DynamicSqlSource转换为StaticSqlSource
静态sql就直接生成了RawSqlSource,内部持有StaticSqlSource
看下生成的boundSql:
后续的执行流程就和getById一样了。
继续下一个sql(返回Map对象):
<select id="getCityAsMapById" resultType="java.util.Map">
SELECT * FROM city where id = #{id}
</select>