5

我有两张表,“Players”和“Items”。玩家有一个物品清单。我想使用分页检索玩家及其所有物品。我想根据玩家进行分页,而不考虑有多少项目。

所以我做这样的事情:

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 查询那样是未定义的,或者是否有保证的答案。

无论如何,哪些条件查询会给我前 25 个玩家或前 25 个玩家-物品组合(按玩家 ID 排序,然后是物品 ID)?

4

2 回答 2

11

来自 Hibernate 的“高级问题”常见问题解答:

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

为什么基于结果集行的“限制”操作(例如 setFirstResult(5) 和 setMaxResults(10))不适用于这些急切的获取查询,这也应该很明显。如果将结果集限制为一定数量的行,则会随机截断数据。有一天,Hibernate 可能足够聪明,知道如果您调用 setFirstResult() 或 setMaxResults(),它不应该使用连接,而是使用第二个 SQL SELECT。试试看,你的 Hibernate 版本可能已经足够聪明了。如果没有,请编写两个查询,一个用于限制内容,另一个用于急切获取。

换句话说,Hibernate 不支持这一点。如果您更聪明并且知道 Hibernate 是如何实现的,那么很明显 setFirstResult 和 setMaxResults 在所有情况下都不会像分页一样远程执行任何操作。很明显,它不需要记录。

于 2011-06-17T22:33:54.900 回答
6

可以肯定,但不是 100%,它将执行以下操作:

它将加入玩家和物品,按 playerID 排序并获取前 25 个结果,所有这些都在一个 SQL 查询中。根据这些数据,它会创建玩家和物品,这将导致任意数量的玩家(小于或等于 25)总共有 25 个物品。最后一个玩家可能没有获得所有物品。

要获得 25 个玩家,请避免FetchMode.JOIN(为避免 N+1 问题,请在映射文件中使用 batch-size):

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();

如果没有从项目到播放器的导航,您可以添加一个。

于 2011-06-16T06:55:12.130 回答