Список разделов для ошибки"максимальное количество выражений в списке - 1000"

user3369592 спросил: 12 мая 2018 в 05:13 в: java

Я передал список с более чем 1000 элементами в запросе HQL и пропустил эту ошибку.

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 на несколько подписок в моем коде?


2 ответа

Есть решение
YCF_L ответил: 12 мая 2018 в 12:49

Ошибка ясна, просто разделите свой огромный список на небольшой список, чем передайте их в свой запрос, если вы используете Java 8+, вы можете использовать этот метод. Разделите список на списки n размера в Java 8 на Szymon Stepniak ,

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 sublist ... до n sublist

user3369592 ответил: 12 мая 2018 в 08:07
вы имеете в виду inClause + = или +"r.uid in?" + i;
YCF_L ответил: 12 мая 2018 в 12:49
@ user3369592 извините, я имею в виду, что я забыл плюс
Esteban ответил: 12 мая 2018 в 05:44

попробуйте использовать кортежи или, если возможно, дополнительный запрос.

  • 1000 элементов, таких как IN (1, 2, 3, ..., 1000)
  • Нет предел числа множеств: IN ((1), (2), (3), ...) < === NOT REMOVE! См. Ниже
  • В подзапросах нет ограничений: IN (SELECT ...)