Mybatis 使用拼接的 ids 查询多个却只得到一条记录
请求参数里使用数组传递多个 id 值,然后在 java 程序中通过循环拼接分割符,最后传递 String 类型参数到 mybatis sql 查询中。调试发现,拼接后的 ids 只返回了一条数据。
StringBuilder idBuiler = new StringBuilder();
for (Integer suId : spApplyDto.getSuIds()) {
idBuiler.append(suId).append(",");
}
// idBuiler.replace(idBuiler.length()-1, idBuiler.length(), "");
String ids = idBuiler.substring(0, idBuiler.length()-1); // ids:'4,2,3'
当然数组拼接字符串还可以这样(百度AI解答):
String ids = Arrays.toString(spApplyDto.getSuIds()).replaceAll("[\\[\\]]", "").trim();
通过数组的 toString 方法返回字符串([4,2,3]
),再把数组转化的字符串前后中括号通过空字符替换掉,最后去除所有的空白、换行符之类的内容。
两种方法不影响输出的结果:4,2,3
。查看调试面板下的 sql 输出:
==> Preparing: select xx from sp_user as su left join sp_flow as sf on sf.id = su.flow_id where su.id in (?) and su.state = '1' order by sf.level asc
==> Parameters: 4, 2, 3(String)
<== Columns: id, flow_id, user_id, user_name, created_at, created_user, updated_at, updated_user, state, state_name, type, level, is_final
<== Row: 4, 1, xx, xx, 2024-05-30 16:45:51, xx, null, null, 1, 正常, 0, 0, 0
<== Total: 1
重点在于参数是 String 类型来着,所以真实的查询变成了 where su.id in ('4, 2, 3')
,拿 sql 到数据库实测,确实只返回一条数据。
想起之前遇到过一次 Mybatis order by id #{order} 变量传入不进去,当时讨论过 #{}
用于预处理语句,${}
是原样输出。所以这里应该修改成后者,使用字符串原样输出,这样可以识别成多个 id。
<select id="selectSpUserListByIds" parameterType="String" resultMap="SpUserResult">
<include refid="selectSpUserVo"/>
where su.id in (${ids}) and su.state = '1'
order by sf.level asc
</select>
再次调试,报错:nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'ids' in 'class java.lang.String'
。
作为 String 参数,ids 在 #{}
中是可以正常识别的,但到了 ${}
突然提示找不到 getter,这让我很意外。有点不太清楚怎么回事,但之前 Mybatis 批量更新报错:Parameter 'orderList' not found. Available parameters are [collection, list] 遇到过,此时添加 @Param("ids")
标识参数名称即可。
再次运行,成功!
当然还可以通过 mybatis 自带的 foreach 循环来实现:直接传入 String[] ids
参数(因为请求传入参数为拼接后的字符串,通过 str.split(",")
转换就得到了 String[]
类型):
<delete id="deleteSpUserByIds" parameterType="String">
update sp_user set state = '0' where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
参数都是通过占位符传入数组中的元素,相比前面原样输出传入安全性更高。