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

情景:最近遇到了一个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中写(参考下面的图)
    在这里插入图片描述
  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值