I've got two tables, 'Players' and 'Items'. Players have a list of items. I want to retrieve the players, and all of their items, using pagination. I want to paginate based on the players and without regard to how many items there are.
So I do something like this:
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();
Is this going to give me the first 25 players, or will it give me the first 25 items (grouped by players)? I'm wondering if this behavior is undefined like it would be for JPA queries, or if perhaps there's a guaranteed answer.
Regardless, what are Criteria queries that would give me the first 25 players or the first 25 player-item combinations (ordered by player ID, then item ID)?
Criteria in Hibernate can be used for join queries by joining multiple tables, useful methods for Hibernate criteria join are createAlias(), setFetchMode() and setProjection() Criteria in Hibernate API can be used for fetching results with conditions, useful methods are add() where we can add Restrictions.
FetchType. In general, FetchMode defines how Hibernate will fetch the data (by select, join or subselect). FetchType, on the other hand, defines whether Hibernate will load data eagerly or lazily.
uniqueResult() Convenience method to return a single instance that matches the query, or null if the query returns no results. Method Detail.
createAlias. Join an association using the specified join-type, assigning an alias to the joined association. The joinType is expected to be one of CriteriaSpecification.
From the "Advanced Problems" FAQ for Hibernate:
http://community.jboss.org/wiki/HibernateFAQ-AdvancedProblems
It should be also obvious why resultset row-based "limit" operations, such as setFirstResult(5) and setMaxResults(10) do not work with these kind of eager fetch queries. If you limit the resultset to a certain number of rows, you cut off data randomly. One day Hibernate might be smart enough to know that if you call setFirstResult() or setMaxResults() it should not use a join, but a second SQL SELECT. Try it, your version of Hibernate might already be smart enough. If not, write two queries, one for limiting stuff, the other for eager fetching.
In other words, Hibernate does not support this. If you were smarter and knew how Hibernate was implemented, it should have been obvious that setFirstResult and setMaxResults doesn't do anything remotely like pagination in all cases. It was so obvious that it does not need documenting.
Quite sure, but not 100%, it will do the following:
It will join the players and the items, order by playerID and take the first 25 results, all in one SQL query. From this data, it creates the players and items, which will result in an arbitrary amount of players (less or equal then 25) with a total of 25 items. It may happen that the last player doesn't get all items.
To get 25 players, avoid FetchMode.JOIN
(to avoid the N+1 problem, use batch-size in the mapping file):
List<Player> first25Players = session
.createCriteria(Players.class)
.addOrder(Order.asc("playerID"))
.setMaxResults(25)
.list();
To get 25 items, start the query by Item, not Player.
List<Item> first25Items = session
.createCriteria(Item.class)
.addOrder(Order.asc("player")) // assuming that player is available
.setMaxResults(25)
.list();
If there is no navigation from the item to the player, you may add one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With