错误“列表中表达式的最大数目为1000”的分区列表

elcex8rz  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(335)

我在一个hql查询中传递了一个包含1000多个元素的列表,结果出现了这个错误

maximum number of expressions in a list is 1000

我读了几篇关于stackoverflow的文章,其中建议将列表划分为几个子列表。

Query query = session.createQuery(
  "SELECT r.subject, COUNT(DISTINCT ss.id), COUNT(DISTINCT r.uid)\n" +
  "FROM " + R.class.getName() + " r\n" +
  "," + SS.class.getName() + " ss\n" +
  "WHERE r.id = ss.id\n" +
  "AND r.uid in (:listMoreThan1000)\n" +
  "GROUP BY r.subject\n"
);
query.setParameterList("listMoreThan1000", listMoreThan1000);
List<Object[]> rows = query.list();
// code to parse the rows

我是hql查询的新手,谁能告诉我如何分区 listMoreThan1000 在我的代码里有几个子列表?

s8vozzvw

s8vozzvw1#

尝试使用元组,或者如果可能的话使用子查询。
1000项,如(1,2,3,…,1000)
对集合数量没有限制:在((1),(2),(3),…)*<==不删除!*见下文
子查询中没有限制:in(select…)

os8fio9y

os8fio9y2#

错误很明显,只需将您的大列表拆分为小列表,然后将它们传递给您的查询,如果您使用的是java 8+,您可以使用此方法将java 8中的列表按szymon stepniak拆分为n个大小的列表,

private static <T> Collection<List<T>> partition(List<T> list, int size) {
    final AtomicInteger counter = new AtomicInteger(0);

    return list.stream()
            .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size))
            .values();
}

您的服务可以如下所示:

List<String> listMoreThan1000 = ...;
int size = 1000;
Collection<List<String>> split = partition(listMoreThan1000, size);
String inClause = "", or = "";
for (int i = 0; i < split.size(); i++) {
    inClause += or + "r.uid in ?" + i;
    or = " OR ";
}
String query = String.format("SELECT r.subject, COUNT(DISTINCT ss.id), COUNT(DISTINCT r.uid)" +
        " FROM %s r, %s ss" +
        " WHERE r.id = ss.id" +
        " AND %s GROUP BY r.subject", R.class.getName(), SS.class.getName(), inClause);

Query query = session.createQuery(query);
for (int i = 0; i < split.size(); i++) {
    query.setParameter("?" + i, split.get(i));
}

List<Object[]> rows = query.list();

最后的查询应该如下所示:

SELECT r.subject, COUNT(DISTINCT ss.id), COUNT(DISTINCT r.uid)
FROM R r, SS ss
WHERE r.id = ss.id
AND r.uid in ?1 OR r.uid in ?2 OR r.uid in ?3 GROUP BY r.subject

注意这部分:

r.uid in ?1 OR r.uid in ?2 OR r.uid in ?3

这将检查uid是否存在于第一个子列表或第二个子列表中。。。直到n子列表

相关问题