【问题标题】:partition list for the error "maximum number of expressions in a list is 1000"错误“列表中的最大表达式数为 1000”的分区列表
【发布时间】:2018-11-15 08:30:28
【问题描述】:

我在 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 划分为几个子列表?

【问题讨论】:

  • 拆分列表与hql无关。用java代码做,多次调用Statement。

标签: java mysql sql oracle hql


【解决方案1】:

尝试使用元组或子查询(如果可能)。

  • 1000 项,例如 IN (1, 2, 3, ..., 1000)
  • 组数没有限制:IN ((1), (2), (3), ...) *
  • 子查询没有限制:IN (SELECT ...)

【讨论】:

    【解决方案2】:

    错误很明显,只需将您的大列表拆分为小列表而不是将它们传递给您的查询,如果您使用的是 Java 8+,您可以使用 Szymon Stepniak 的此方法Divide a list to lists of n size in Java 8

    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 是否存在于第一个子列表或 2ed 子列表中...直到 n 个子列表

    【讨论】:

    • 你的意思是inClause += 还是+ "r.uid in ?" +我;
    • @user3369592 抱歉,是的,我的意思是我忘了加号
    猜你喜欢
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多