大家好久没见了,最近在项目中遇到个Mybatis参数绑定的坑,Mybatis在参数绑定时如果没有key,Map和List<Map>将有不同的结果。
一、参数是Map的绑定
-
创建一个name和age为key的map。
public Object test() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("name", "wtao");
params.put("age", 18);
Map<String, Object> resultMap = oaMapper.test(params);
return resultMap;
}
- 测试用的mapper
public Map<String, Object> test(Map<String, Object> map);
- 映射xml的sql,简单起见只将参数直接输出,关键点是map中没有abc的key,看mybatis如何生成sql
<select id="test" parameterType="map" resultType="map">
SELECT
#{name,jdbcType=VARCHAR} name,
#{age,jdbcType=VARCHAR} age,
#{abc,jdbcType=VARCHAR} abc
FROM DUAL
</select>
运行结果如图:可以看出Mybatis以Map为参数在绑定时如果获取的变量名称如果在map中未定义,则会赋值为null。
二、参数是List<Map>的绑定
- 定义2个Map放到List中
public Object test() throws Exception {
Map<String, Object> params = new HashMap<>();
params.put("name", "wtao");
params.put("age", 18);
Map<String, Object> params1 = new HashMap<>();
params1.put("name", "xiaoli");
params1.put("age", 24);
List<Map<String, Object>> list = new ArrayList<>();
list.add(params);
list.add(params1);
List<Map<String, Object>> resultList = oaMapper.test(list);
return resultList;
}
- 修改mapper
public List<Map<String, Object>> test(List<Map<String, Object>> list);
- 映射xml的sql,因为是List需要使用foreach标签,循环取出结果,还是没有abc的key,看生成的sql
<!-- 测试查询 -->
<select id="test" resultType="map">
<foreach collection="list" item="item" separator=" union all ">
SELECT
#{item.name,jdbcType=VARCHAR} name,
#{item.age,jdbcType=VARCHAR} age,
#{item.abc,jdbcType=VARCHAR} abc
FROM DUAL
</foreach>
</select>
运行结果如图:可以看出Mybatis以List<Map>为参数在循环绑定内部如果获取的变量名称在map中未定义,Mybatis不会设置默认值null,因此会直接抛出异常。
处理:虽然直接取值会出异常,可用在if判断时却没问题,可以改成这样
<!-- 测试查询 -->
<select id="test" resultType="map">
<foreach collection="list" item="item" separator=" union all ">
SELECT
#{item.name,jdbcType=VARCHAR} name,
#{item.age,jdbcType=VARCHAR} age
<if test="item.abc != null">
, #{item.abc,jdbcType=VARCHAR} abc
</if>
FROM DUAL
</foreach>
</select>
三、总结
在使用Mybatis时Map和List<Map>的参数绑定认为Mybatis会有相同的绑定机制,结果发现却不同,所以在使用的时候请格外注意List<Map>中没有变量名称的情况。
(完)