Mybatis源码阅读8 --- sql语句的一切(2)

继上篇分析了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>

猜你喜欢

转载自blog.csdn.net/lnlllnn/article/details/80993348