使用Hibernate条件和FetchMode.JOIN进行分页

时间:2011-06-16 00:34:18

标签: hibernate hibernate-criteria

我有两张桌子,'玩家'和'物品'。玩家有一个项目列表。我想使用分页来检索玩家及其所有物品。我想根据玩家分页,而不考虑有多少项目。

所以我这样做:

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名玩家项目组合(按玩家ID排序,然后按项目ID排序)?

2 个答案:

答案 0 :(得分:9)

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

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

  

为什么也应该是显而易见的   结果集基于行的“限制”   操作,例如setFirstResult(5)   和setMaxResults(10)不起作用   带着这种渴望的获取   查询。如果将结果集限制为   一定数量的行,你切断了   数据随机。有一天Hibernate可能   要聪明,知道如果你   调用setFirstResult()或   setMaxResults()它不应该使用   join,但是第二个SQL SELECT。试试吧,   您的Hibernate版本可能   已经足够聪明了。如果没有,请写信   两个查询,一个用于限制内容,   另一个是渴望获取。

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

答案 1 :(得分:6)

很确定,但不是100%,它会执行以下操作:

它将加入玩家和项目,按玩家ID排序并获取前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();

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