Подтвердить что ты не робот

API Hibernate Criteria: получить n случайных строк

Я не могу понять, как извлечь n случайных строк из экземпляра критериев:

Criteria criteria = session.createCriteria(Table.class);
criteria.add(Restrictions.eq('fieldVariable', anyValue));
...

Тогда что? Я не могу найти какой-либо документ с API критериев

Означает ли это, что я должен использовать HQL вместо этого?

Thanx!

EDIT: я получаю количество строк:

int max = criteria.setProjecxtion(Projections.rowCount()).uniqueResult();

Как получить n случайных строк с индексами от 0 до макс? спасибо снова!

4b9b3361

Ответ 1

На самом деле это возможно с критериями и немного настройки. Вот как это делается:

Criteria criteria = session.createCriteria(Table.class);
criteria.add(Restrictions.eq("fieldVariable", anyValue));
criteria.add(Restrictions.sqlRestriction("1=1 order by rand()"));
criteria.setMaxResults(5);
return criteria.list();

любые Restrictions.sqlRestriction будут добавлять ключевые слова 'и'; чтобы свести на нет его эффект, мы добавим фиктивное условие и добавим нашу функцию rand().

Ответ 2

Прежде всего, имейте в виду, что в SQL нет стандартного способа сделать это, каждый механизм базы данных использует собственный собственный синтаксис 1. С MySQL оператор SQL для получения 5 случайных строк будет:

SELECT column FROM table
ORDER BY RAND()
LIMIT 5

И вы можете написать этот запрос в HQL, потому что предложение order by в HQL передается в базу данных, чтобы вы могли использовать любую функцию.

String query = "SELECT e.attribute FROM MyEntity e ORDER BY RAND()";
Query q = em.createQuery(query);
q.setMaxResults(5);

Однако, в отличие от HQL, API критериев в настоящее время не поддерживает ORDER BY Native SQL (см. HHH-2381) и в текущем состоянии, вам необходимо подклассифицировать класс Order для реализации этой функции. Это выполнимо, см. Вопрос Jira, но не доступен из коробки.

Итак, если вам действительно нужен этот запрос, моя рекомендация будет заключаться в использовании HQL. Просто имейте в виду, что он не будет переносимым.

1 Другие читатели могут захотеть проверить сообщение SQL для выбора случайной строки из таблицы базы данных, чтобы увидеть как реализовать это с MySQL, PostgreSQL, Microsoft SQL Server, IBM DB2 и Oracle.

Ответ 3

API критериев не предоставляет для этого никаких возможностей. Однако в MySQL вы можете использовать ORDER BY RAND() LIMIT n для этого, где n представляет количество случайных строк, которые вы хотите извлечь.

SELECT col1, col2, col3 FROM tbl ORDER BY RAND() LIMIT :n

Вам действительно нужно выполнить его как HQL.

Ответ 4

Вы не можете получать случайные строки эффективно, извините. Hibernate может делать только то, что делает SQL, а случайная выборка строк просто не является частью какой-либо стандартной реализации SQL, которую я знаю. На самом деле это, насколько мне известно, не является частью ANY SQL, о которой я знаю (кто-нибудь, пожалуйста, просветите меня).

И поскольку Hibernate - это O/R-сопоставитель, а не чудо-машина, он может делать только то, что поддерживает базовая база данных.

Если у вас есть известная поданная с восходящими номерами и знающая начало и конец, вы можете создать случайный номер на компьютере и запросить эту строку.

Ответ 5

Ответ @PSV Bhat затруднен, если вы динамически генерируете свои критерии. Вот решение, расширяющее класс Order в спящем режиме:

import org.hibernate.Criteria;
import org.hibernate.criterion.Order;

private void addOrderByToCriteria(Criteria criteria) {
    criteria.addOrder(Order.asc("foobar"));
    criteria.addOrder(ORDER_RANDOM);
}

private static final OrderRandom ORDER_RANDOM = new OrderRandom();

private static class OrderRandom extends Order {
    public OrderRandom() {
        super("", false);
    }
    @Override
    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
        return "RANDOM()"; // or RAND() or whatever this is in your dialect
    }
}