目录
当我们使用在mapper.xml文件中写sql时,in占位符过多,会导致报下面的异常:
org.springframework.jdbc.BadSqglGrammarException: ###Error querying database.Cause: java.sq.SQLSyntaxErrorException:ORA-01795:列表中的最大表达式数为1000
mapper.xml文件和Dao层、service层是下面这样的
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.xxx.zygxsq.aaaaaaDao">
<select id="getXxxxxxInfo" resultType="com.xxx.xxx.zygxsq.model.Aaaaaaaa">
SELECT
aa,
bb,
cc
FROM AaaaTable T
<where>
<if test="namesList != null and namesList.size() > 0 ">
T.NAME in
<foreach collection="namesList" item="name" separator="," open="(" close=")">
#{name}
</foreach>
</if>
</where>
</select>
</mapper>
Dao层:
@Mapper
public interface aaaaaaDao {
List<StudentDTO> getXxxxxxInfo(@Param(value = "nameList") List<String> nameList);
}
service层
@Slf4j
public class BbbbbbbServiceImpl implements BbbbbbbService {
@Autowired
AaaaaaDao aaaaaaDao;
@Override
private void getXxxxxxInfo() {
List<StudentDTO> list = aaaaaaDao.getXxxxxxInfo(nameList);
return null;
}
}
上述mapper.xml就会出现,如果nameList的长度过大,大于1000的话,就会报上述异常 :Error querying database.Cause: java.sq.SQLSyntaxErrorException:ORA-01795:列表中的最大表达式数为1000,
那应该怎么改呢,可以将超过1000的变成or的形式
正确的mapper.xml、Dao层、Service层如下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxx.xxx.zygxsq.aaaaaaDao">
<select id="getXxxxxxInfo" resultType="com.xxx.xxx.zygxsq.model.Aaaaaaaa">
SELECT
aa,
bb,
cc
FROM AaaaTable T
<where>
<if test="namesList != null and namesList.size() > 0 ">
AND
<foreach collection="namesList" item="names" separator="or">
T.NAME in
<foreach collection="names" item="name" separator="," open="(" close=")">
#{name}
</foreach>
</foreach>
</if>
<if test="sex!=null">
AND sex= #{sex}
</if>
</where>
</select>
</mapper>
Dao层
@Mapper
public interface aaaaaaDao {
List<StudentDTO> getXxxxxxInfo(@Param(value = "nameList") List<List<String>> nameList);
}
service层
@Slf4j
public class BbbbbbbServiceImpl implements BbbbbbbService {
@Autowired
AaaaaaDao aaaaaaDao;
@Override
private void getXxxxxxInfo() {
// 切割超过1000的变成多个list
List<List<String>> sumArrayCodeList = CommonUtil.getSumArrayList(nameList);
List<StudentDTO> list = aaaaaaDao.getXxxxxxInfo(sumArrayCodeList);
return null;
}
}
getSumArrayList 工具类方法,可以有多种实现方式
方式一
/**
* oracle超过1000拆分list
* @param list
* @param <T>
* @return
*/
public static <T> List<List<T>> getSumArrayList(List<T> list) {
int maxSize = 1000;
int one = 1;
int zero = 0;
List<List<T>> objectlist = new ArrayList<>();
if (CollectionUtils.isEmpty(list)) {
return objectlist;
}
int iSize = list.size() / maxSize;
int iCount = list.size() % maxSize;
for (int i = 0; i <= iSize; i++) {
List<T> newObjList = new ArrayList<>();
if (i == iSize) {
for (int j = i * maxSize; j < i * maxSize + iCount; j++) {
newObjList.add(list.get(j));
}
} else {
for (int j = i * maxSize; j < (i + one) * maxSize; j++) {
newObjList.add(list.get(j));
}
}
if (newObjList.size() > zero) {
objectlist.add(newObjList);
}
}
return objectlist;
}
方式二
/**
* 列表分页
* Oracla中In参数超过1000会抛出异常
*
* @param list 源列表
* @param max 每页最多数据量
* @return 分页列表
*/
public static <T> List<List<T>> getSumArrayList(List<T> list, int max) {
List<T> templist;
List<List<T>> pageList = new ArrayList<>();
if (CollectionUtils.isEmpty(list)) {
log.warn("参数列表为空!");
return Collections.emptyList();
}
// 去重
log.debug("去重前长度" + list.size());
templist = list.stream().distinct().collect(Collectors.toList());
log.debug("去重后长度" + list.size());
// 总页数
int pageTotalNum = (int) Math.ceil(templist.size() / (max * 1.0));
for (int i = 0; i < pageTotalNum; i++) {
pageList.add(templist.stream().skip(i * max).limit(max).collect(Collectors.toList()));
}
return pageList;
}
方式三
/**
* 数据库in ()切割
* @param data
* @return
*/
public static List<List<String>> getSumArrayList(List<String> data) {
private static final Integer MAX_SEND = 999;
int size = data.size();
int limit = (size + MAX_SEND - 1) / MAX_SEND;
return Stream
.iterate(0, n -> n + 1).limit(limit).parallel()
.map(a -> data.stream().skip(a * MAX_SEND).limit(MAX_SEND).parallel().collect(Collectors.toList()))
.collect(Collectors.toList());
}