- 开头
- 区别
- 运行结果分析
- 解决办法
开头
在每日一篇技术文章研读过程中,工作发狂:MyBatis 中 $ 和 # 千万不要乱用! 学习了 在Mybatis文件中 # 和 $ 好的理论知识。忍不住自己动手实践一遍。
下面为测试的的代码:
XXXMappMapper.java
List<StatisticsInfo> selectByExampleByIdList(@Param("idList") String idList);
List<StatisticsInfo> selectByExampleByIdList2(@Param("idList") String idList);
XXXMapper.xml
<select id="selectByExampleByIdList" resultMap="BaseResultMap">
select * from biz_statistics_info where id in(#{idList})
</select>
<select id="selectByExampleByIdList2" resultMap="BaseResultMap">
select * from biz_statistics_info where id in(${idList})
</select>
调用时打印的sql日志。
2019-07-25 13:51:36.860 [main] DEBUG com.angzk.dao.mapper.StatisticsInfoMapper.selectByExampleByIdList - ==> Preparing: select * from biz_statistics_info where id in(?)
2019-07-25 13:51:36.895 [main] DEBUG com.angzk.dao.mapper.StatisticsInfoMapper.selectByExampleByIdList - ==> Parameters: 1,2,3,4(String)
2019-07-25 13:51:36.930 [main] DEBUG com.angzk.dao.mapper.StatisticsInfoMapper.selectByExampleByIdList - <== Total: 1
2019-07-25 13:51:36.978 [main] DEBUG com.angzk.dao.mapper.StatisticsInfoMapper.selectByExampleByIdList2 - ==> Preparing: select * from biz_statistics_info where id in(1,2,3,4)
2019-07-25 13:51:36.979 [main] DEBUG com.angzk.dao.mapper.StatisticsInfoMapper.selectByExampleByIdList2 - ==> Parameters:
2019-07-25 13:51:36.992 [main] DEBUG com.angzk.dao.mapper.StatisticsInfoMapper.selectByExampleByIdList2 - <== Total: 4
从Mybatis 打印的sql 日志中可以看到。 #{idList}的时候,参数是一个字符串。而${idList} 的时候参数直接拼接到了 sql 语句上,他们的处理方式不一样。
区别
1.#{}是预编译处理,Mybatis 在处理#{}时,他会将 sql 的#{}替换为 ? 然后调用 PreparedStatement的set方法来赋值(给 ? f赋值),传入字符串后,会在值两边加上单引号,如上面的值 “1,2,3,4”就会变成“ '1,2,3,4' ”;
2.${}是字符串拼接替换,在处理${}是字符串替换,MyBatis 在处理${},会将sql中的它替换为变量的值,传入的值不会加上双边单引号。
3.${}会出现sql 注入,不利于系统安全性。
运行结果分析
#{idList} 的 函数返回了 1条数据。${idList} 的 函数返回了 4条数据。
#{idList} 的sql 语句:select * from biz_statistics_info where id in('1,2,3,4').
由于传入的参数是个 字符串(看图。),id 字段为 int 类型。mysql 通过内置函数 cast 或者 convert 对 '1,2,3,4' 进行类型转换。
所以最终运行sql : select * from biz_statistics_info where id in(1)。然后返回了一条 id = 1 的数据。.
解决方法
使用 foreach 标签。把入参的字符串变成 List
select * from biz_statistics_info where id in
<foreach collection="list" item="item" index="index" open="(",close=")" separator=",">
#{item}
</foreach>
一般情况下,大家使用的 Mapper.xml 都会使用 MyBatis Generator 来自动生成 ,里面有提供的 foreach 代码片段。具体大家可以在使用中自行研究。
补充
关于Mysql 类型转换的文章请移步至此:MySQL 数据类型转换。