我们在查数据库的时候,由于分库或者其他的原因,需要把一部分数据查出来再用作另一个sql的条件,这时就很容易出现 in 超过1000的情况。
这里我只是补充一下网上 id in () or id in () 的具体实现:
入参idList:List<Long> , size大于 1000
1.首先,最好不要用$符拼接sql语句的方式,sql注入什么的,老问题。
这个idList肯定是要切割的,idMutilList:List<List<Long>>
写个切割list的公用方法:
public static <E> List<List<E>> splitList (List<E> targetList,Integer splitSize){
if(targetList == null) return null;
Integer size = targetList.size();
List<List<E>> resultList = new ArrayList<List<E>>();
if(size <= splitSize) {
resultList.add(targetList);
} else {
for (int i = 0; i < size; i += splitSize) {
//用于限制最后一部分size小于splitSize的list
Integer limit = i+splitSize;
if(limit > size){
limit = size;
}
resultList.add(targetList.subList(i, limit));
}
}
return resultList;
}
2.如果你不需要在sql里面进行排序或分页,分批次查数据库,查出来数据之后add到一起就好了,毕竟用or去连接sql性能会很差。
3.mybatis提供了循环的方式foreach(ibatis是一样的,iterate),既然有循环,再套一层就可以处理List<List<Long>>这种入参了
具体的mapper:
AND ( ID IN
<foreach collection="idMutilList" index="index" item="idList" separator=" OR ID IN " >
<foreach collection="idList" index="index" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</foreach>
)
结语:这种方案性能不会很好,oracle sql语句本身有长度限制,若数据量太大了会报sql超长的错误。如果能从业务上拆解sql,找解决方案,那是最好的。如果你的条件允许你在数据库建表(一般不允许在生产环境建表),你可以建个中间表或临时表啥的,数据插进去,两张表的话那就好办了,inner join 或子查询什么的,性能也很好。再不行那就采用第2条说的,自己写排序和分页吧。