Mybatis之前的参数处理方式
org.apache.ibatis.executor.SimpleExecutor#doQuery org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters 这个方法包含了所有参数处理器设置对象的逻辑,传入的参数种类比较多我们一个一个分析
boundSql.hasAdditionalParameter(propertyName)
sql中有foreach标签
parameterObject == null
typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
这部分的情况有点复杂,传入的参数可能是一个Map,也可能是一个TypeHandler解析不了的对象
当你对参数没有设置对应的TypeHandler时,会设置TypeHandler为UnknownTypeHandler, UnknownTypeHandler会根据javaType和jdbcType选取合适的TypeHandler来进行赋值操作
TypeHandler
我们常用的TypeHandler基本上都继承了BaseTypeHandler,这里只是对设置的值为null时,做了统一的处理,不为null时则交给具体的TypeHandler来处理
org.apache.ibatis.type.UnknownTypeHandler#setNonNullParameter
TypeHandlerRegistry构造函数中会初始化常见的映射关系
Mybatis增强后的参数处理方式
当使用Mapper接口的方式来执行sql时,会调用到MapperMethod#execute方法,因为通过Mapper接口调用时,有可能传入多个参数,而SqlSession执行sql时只支持单个参数,所以我们要通过执行method.convertArgsToSqlCommandParam(args)将多个参数合并为一个参数,那么合并的逻辑是怎样的? 在MapperMethod构造上中创建MethodSignature的时候,会对每个方法创建一个ParamNameResolver 构造函数主要作用就是构造names,保存参数位置和参数名称的映射关系,后续会用。分为两种情况加了@Param注解,和没有加@Param注解
@Select("SELECT * FROM user_info WHERE name = #{name} and age = #{age}")
UserInfo selectByNameAndAge(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM user_info WHERE id = #{id} and age = #{age}")
UserInfo selectByIdAndAge(Integer id, Integer age);
MapperMethod.MethodSignature#convertArgsToSqlCommandParam
可以看到主要分为3个部分
args == null || paramCount == 0
!hasParamAnnotation && paramCount == 1
当只有一个入参,且是集合类型时,做了一些特殊的处理 逻辑比较简单,就是给参数多起了一些别名
List<UserInfo> selectByIds(List<Integer> ids);
<foreach collection="arg0" open="(" close=")" separator="," item="item">
<foreach collection="collection" open="(" close=")" separator="," item="item">
<foreach collection="list" open="(" close=")" separator="," item="item">
接着就是最后一种情况,用了@Param注解或者有多个参数
UserInfo selectByNameAndAge(@Param("name") String name, @Param("age") Integer age);
@Select("SELECT * FROM user_info WHERE name = #{name} and age = #{age}")
@Select("SELECT * FROM user_info WHERE name = #{param1} and age = #{param2")
UserInfo selectByIdAndAge(Integer id, Integer age);
@Select("SELECT * FROM user_info WHERE id = #{arg0} and age = #{arg1}")
@Select("SELECT * FROM user_info WHERE id = #{param1} and age = #{param2}")
参考博客
|