背景
1.1 一个SQL查询 比如下面的
<sql id="selectCount"> select count(*) from `user` <where> <if test="names != null and names.size > 0"> name in ( <foreach collection="names" item="name" separator=","> #{name} </foreach> ) </if> <if test="name != null"> name = #{name} </if> </where> </sql>
1.2 UserMapper
@Mapper
public interface UserMapper { int selectCount(Map<String,Object> param);
}
1.3 查询
@SpringbootApplication public class Application { @Autowired UserMapper userMapper; @Test public void test() { Map<String,Object> param = new HashMap<>();
param.put('names', Lists.newArrayList('张三','李四','王五')); userMapper.selectCount(param);
// 1. 期望执行的SQL: select count(*) from `user` where name in ('张三','李四','王五');
// 2. 结果执行的SQL: select count(*) from `user` where name in ('张三','李四','王五') and name = '王五';
) } }
2. 如何修改
2. 1 调整SQL (第一种方案: foreach 部分放在下面; 第二种方案: foreach的 item 属性不与下方的参数相同 如使用 'nameTemp')
<sql id="selectCount"> select count(*) from `user` <where> <if test="name != null"> name = #{name} </if>
<if test="names != null and names.size > 0"> name in ( <foreach collection="names" item="name" separator=","> #{name} </foreach> ) </if> </where> </sql>
2. 2 升级mybaits 版本 3.5
3. 原因简说
1. mybatis在组装动态SQL时将方法所有的参数转为map, 解析每个动态SQL节点的时,会将这些参数替换进去。
2. 当解析foreach节点时,由于item 属性的存在,会将item也做作为参数放在map里,当解析后续的动态SQL时,就导致使用到item属性。 而高版本的mybaits 是 当解析完一个foreach动态SQL节点会移除这些组装过的属性。就不存在item会影响后面的动态SQL节点;
主要涉及代码类: org.apache.ibatis.scripting.xmltags.DynamicContext; org.apache.ibatis.scripting.xmltags.ForEachSqlNode#apply(DynamicContext context)
)
浙公网安备 33010602011771号