select...in在mybatis里使用(巨坑!!)

发布时间:2024年01月19日

情景:最近遇到了一个bug:在这里插入图片描述
在DAO层里的这个sql语句,传入的参数没问题,在mysql里面查询也查询到了数据,为什么在dao层执行的时候查到数据不完整甚至没有呢?

主要原因:
Mybatis 在 处理#{}时,#{}传入参数是以字符串传 入 , 会将SQL 中的#{}替 换 为 ? 号 , 调 用 PreparedStatement 的 set 方法来赋值。
Mybatis 在 处理${}时是原值传入 ,就 是把{} 替换 成变量的 值,相当于 JDBC 中的 Statement 编译变量替换 后 ; #{} 对应的变量自动加上单引号 ‘’ ; 变量替换后, ${} 对应 的变量不会加上单引号 ‘’。
也就是说,如果按#{}的话,传入的参数classIds为"210901,210900,210899,210898,210897",再加上单引号,我们只能使用到第一个参数!也就是变成了select in 210901,而不是select in 210901,210900...

关于#{},${}:
where name in ('Jana','Tom');

我们可以在sql中直接写 name in ('Jana','Tom') 或者 name in (${names}) (备注:String names = " ‘Jana’, ‘Tom’ ";
(使用$时会引起sql注入安全问题)
但是我们无法在sql中直接写 name in (#{names});
会报参数个数错误,因为’Jana’,'Tom’会被解析成两个传参
String[] names={"Jana","Tom"};

解决方式
一, 使用${}
不过有注入风险
二,在select注解中。利用<foreach></foreach>标签来遍历数组中的元素,在放入in()中。这个时候,我们传入的参数需要是List形式,而不是String。
要在@Select注解里面使用in查询需要有特定的语法和规则,有点类似XML的写法

@Select({"<script>",
        " select ",
        " ah.id homeworkId, ah.homeworkTitle, ah.homeworkType, ah.grade, ah.createTime ",
        " from hw_activityhomework_tab ah ",
        " inner join hw_classhomework_tab ch on ah.id = ch.acthomeworkid ",
        " where ch.classId in ",
        " <foreach collection='classIds' item='classId' open='(' separator=',' close=')'> ",
        " #{classId} ",
        " </foreach> ",
        " and ah.homeworkType in ",
        " <foreach collection='typeStrs' item='typeStr' open='(' separator=',' close=')'> ",
        " #{typeStr} ",
        " </foreach> ",
        " group by ah.id ",
        " order by ah.homeworkType desc, ah.createTime desc ",
        " </script>"})
    List<HomeworkAndScoreDTO> getOcHomeworkAndScore(@Param("classIds") String[] classIds, @Param("typeStrs")String[] typeStrs);
  • 要有<script>标签
  • open='(' separator=','中,‘(’ 和 separator中间要有空格,否则会报错
    三,在xml中写(参考下面的图)
    在这里插入图片描述
文章来源:https://blog.csdn.net/m0_53098280/article/details/135693834
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。