天天看点

mybatisplus动态sql整型数组使用in踩坑

背景

项目中有个需求,根据多个整型id查询对应的信息

理论上最终sql应该是如下所示:

select userName form t_user where userId in(1,2,3,4,5,6);      

但前端传来的参数

Integer[] userIdArr      

想着就把userIdArr转成1,2,3,4,5,6就行了

/**
     * [1,2,3] to 1,2,3
     *
     * @return
     */  
public static String intArrToString(Integer[] arr) {
        return StringUtils.join(arr, ",");
    }      

然后将字符串形式的userArrIds作为参数传给mappe,于是写成动态sql如下

@Select("select userName from t_user where userId in (#{userArrIds})")
List<String> getUserNameByUserIds(String userArrIds);      

按照预想的,它应该生成如下sql语句

select userName form t_user where userId in(1,2,3,4,5,6);      

自测一下,发现无论userIdArr传多少个,都只能查出第一个,郁闷了半天

才发现被自己“蠢哭了”,因为将Integer[] userIdArr转换成了String,最终的sql其实是这样的

select userName form t_user where userId in('1,2,3,4,5,6');      

整个参数被当成了一个完整的字符串

使用QueryWrapper

既然发现了问题,这条路就走不通了,换一个方法实现,还是将Integer[] userIdArr转换成String,这回用com.baomidou.mybatisplus.core.conditions.query.QueryWrapper来生成动态sql

List<UserDo> userList = userMapper.selectList(new QueryWrapper<UserDo>().inSql("userID",result).select("userName"));      

这样结果是查出来了,但也有个问题,因为在定义BaseMapper的时候项目组已经约定了泛型为UserDo,所以用QueryWrapper查询返回值只能是UserDo的列表或单行,如果我需要其他想要的类型都只能通过额外的转换。

@Repository
public interface UserMapper extends BaseMapper<UserDo> {

…………………………
}      

比如我这只需要返回一个List<userName>,拿到数据后还需要转换一下,虽然转换并不难,但还是觉得有点多余。

List<String> userNameList = userDoList.stream().map(UserDo::getuserName).collect(Collectors.toList());      

@Select+script

鉴于上面的方法存在两个不优雅的问题

  • 需要将整形数组参数转换成字符串
  • 返回结果需要二次转换

查阅了很多资料后,发现一个更好的实现方法,既不需要转换入参,也可以按自己的需求决定返回值。

@Select("<script> " +
            "select userNanme from t_user where  userId " +
            "in <foreach item='item' index='index' collection='userIdArr' open='(' separator=',' close=')'> #{item} </foreach> " +
            "</script>")
    List<String> getUserNameByUserIds(Integer[] userIdArr);