Разбивка на страницы с критериями гибернации и FetchMode.JOIN - PullRequest
4 голосов
/ 16 июня 2011

У меня есть два стола: «Игроки» и «Предметы». У игроков есть список предметов. Я хочу получить игроков и все их предметы, используя нумерацию страниц. Я хочу разбивать на страницы, основываясь на игроках и не обращая внимания на количество предметов.

Итак, я делаю что-то вроде этого:

Criteria c = session.createCriteria(Players.class).setFetchMode("items", FetchMode.JOIN);
c.addOrder(Order.asc("playerID"));
c.setFirstResult(0);
c.setMaxResults(25);
List<Player> players = c.list();

Это даст мне первых 25 игроков или первые 25 предметов (сгруппированных по игрокам)? Мне интересно, если это поведение не определено, как это было бы для запросов JPA, или, возможно, есть гарантированный ответ.

Независимо от того, что за запросы Criteria дают мне первые 25 игроков или первые 25 комбинаций игрок-предмет (упорядоченные по идентификатору игрока, затем по идентификатору предмета)?

Ответы [ 2 ]

9 голосов
/ 18 июня 2011

Из часто задаваемых вопросов "Расширенные проблемы" для Hibernate:

http://community.jboss.org/wiki/HibernateFAQ-AdvancedProblems

Должно быть также очевидно, почему основанные на строке результатов операции "ограничения", такиетак как setFirstResult (5) и setMaxResults (10) не работают с такими нетерпеливыми запросами на выборку.Если вы ограничите набор результатов определенным количеством строк, вы случайно обрежете данные.Однажды Hibernate может быть достаточно умен, чтобы знать, что если вы вызываете setFirstResult () или setMaxResults (), он должен использовать не соединение, а второй SQL SELECT.Попробуйте, ваша версия Hibernate уже может быть достаточно умной.Если нет, напишите два запроса, один для ограничения содержимого, другой для получения извлечения.

Другими словами, Hibernate не поддерживает это.Если вы были умнее и знали, как реализован Hibernate, должно быть очевидно, что setFirstResult и setMaxResults во всех случаях не делают ничего похожего на нумерацию страниц.Это было настолько очевидно, что не нуждается в документировании.

6 голосов
/ 16 июня 2011

Совершенно уверен, но не на 100%, он будет делать следующее:

Он объединит игроков и предметы, упорядочит по playerID и возьмет первые 25 результатов, все в одном SQL-запросе. Исходя из этих данных, он создает игроков и предметы, в результате чего получается произвольное количество игроков (меньше или равно 25) с общим количеством предметов 25. Может случиться, что последний игрок не получит все предметы.

Чтобы получить 25 игроков, избегайте FetchMode.JOIN (чтобы избежать проблемы N + 1, используйте размер пакета в файле отображения):

List<Player> first25Players = session
  .createCriteria(Players.class)
  .addOrder(Order.asc("playerID"))
  .setMaxResults(25)
  .list();

Чтобы получить 25 предметов, начните запрос по элементу, а не по игроку.

List<Item> first25Items = session
  .createCriteria(Item.class)
  .addOrder(Order.asc("player")) // assuming that player is available
  .setMaxResults(25)
  .list();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...