我有两张桌子,'玩家'和'物品'。玩家有一个项目列表。我想使用分页来检索玩家及其所有物品。我想根据玩家分页,而不考虑有多少项目。
所以我这样做:
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排序)?
答案 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();
如果项目没有导航到播放器,您可以添加一个。