Как это возможно, я имею к следующим критериям
Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
Размер списка равняется теперь 20. Если я добавляю макс. результаты к критериям,
Criteria criteria = getSession().createCriteria(c);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setMaxResults(90);
criteria.add(Restrictions.eq("active",true));
List list = criteria.list();
.. теперь размер списка равняется 18!
Я не понимаю, как размер наборов результатов может быть меньшим после определения макс. результатов, как сумма строк меньше, чем определенный максимум. Это уверенное походит на ошибку или там снова, некоторые странные аспекты в спящем режиме, о котором я не знаю?
При поиске ответа на этот вопрос удостоверьтесь, что прочитали принятый ответ и его комментарии.
То, что здесь происходит, можно очень ясно увидеть, включив отладку SQL в Hibernate и сравнив сгенерированные запросы.
Используя довольно простой Sale
→ Item
сопоставление «один ко многим» (которое, надеюсь, не требует пояснений), запрос на основе Criteria
, подобный этому :
Criteria c = sessionFactory.getCurrentSession().createCriteria(Sale.class);
c.createAlias("items", "i");
c.add(Restrictions.eq("i.name", "doll"));
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.setMaxResults(2);
производит такой SQL:
select top ? this_.saleId as saleId1_1_, ...
from Sale this_
inner join Sale_Item items3_ on this_.saleId=items3_.Sale_saleId
inner join Item items1_ on items3_.items_id=items1_.id
where items1_.name=?
, тогда как Запрос
вроде этого:
Query q = sessionFactory.getCurrentSession().createQuery("select distinct s from Sale s join s.items as i where i.name=:name");
q.setParameter("name", "doll");
q.setMaxResults(2);
производит что-то вроде:
select top ? distinct hibernated0_.saleId as saleId1_
from Sale hibernated0_
inner join Sale_Item items1_ on hibernated0_.saleId=items1_.Sale_saleId
inner join Item hibernated2_ on items1_.items_id=hibernated2_.id
where hibernated2_.name=?
Обратите внимание на разницу в самой первой строке ( DISTINCT
). ResultTransformer
как DISTINCT_ROOT_ENTITY
- это класс Java, который обрабатывает результаты строк SQL после выполнения SQL.Следовательно, когда вы указываете maxResults
, это будет применяться как ограничение строки в SQL; SQL включает объединение элементов в коллекции
, поэтому вы ограничиваете свой результат SQL до 90 подэлементов . После применения преобразователя DISTINCT_ROOT_ENTITY
это может привести к менее чем 20 корневым элементам, в зависимости от того, какие корневые элементы оказываются первыми в 90 объединенных результатах.
DISTINCT
в HQL ведет себя совершенно иначе, поскольку фактически использует ключевое слово SQL DISTINCT
, которое применяется перед ограничением строки. Следовательно, это ведет себя так, как вы ожидаете, и объясняет разницу между 2.
Теоретически вы должны посмотреть на setProjection
, чтобы применить проекцию на уровне SQL - что-то вроде c. setProjection (Projection.distinct (Projection.rootEntity ()))
- но, к сожалению, Projection.rootEntity ()
не существует, я просто придумал.Возможно, стоит!
SetMaxResults не работает с внешним соединением SQL-запросы. Может быть, это ваша проблема: Hibernate не возвращает отчетливые результаты для запроса с внешним присоединением для присоединения включено для коллекции (даже если я использую отличное ключевое слово)? .