Let's say Item and Bid are entities: an Item has many Bids. They are mapped in Hibernate in a typical parent/child relationship:
<class name="Item" table="ITEM">
...
<set name="bids" inverse="true">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>
How can I avoid n+1 selects when trying to access the bids of each Item after this query is executed?
List<Item> items = session.createCriteria(Item.class)
.createAlias("bids", "b").
.add(Restrictions.gt("b.amount", 100)).
.list();
Note I need an eager fetching for bids but with a further restriction on the collection (b.amount > 100)
I've tried the following unsuccessfully:
List<Item> items = session.createCriteria(Item.class)
.setFetchMode("bids", FetchMode.JOIN).
.createAlias("bids", "b").
.add(Restrictions.gt("b.amount", 100)).
.list();
List<Item> items = session.createCriteria(Item.class)
.createCriteria("bids")
.add(Restrictions.gt("amount", 100)).
.list();
Eager fetching is the ability to efficiently load subclass data and related objects along with the base instances being queried.
First one is to create entity graph and including that in graph. So you would fetch data with your graph and that would be it. No more additional sql queries to fetch eager collection. Second solution is to create entity for same table but with everything marked lazy.
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.
This is an explanation of why adding a restriction on the fetch-joined collection causes the collection was not initialized (note that the same query without the restriction produce an eager fetch for the collection):
"If you have a 1:n relation between tables A and B, and you add a restriction to B and want to fetch A and B it eagerly, the question would be what happens when you want to navigate from A to B. Should you only see the data in B that matches the restriction, or should you see all Bs that are related to A?" see more here ...
However, using HQL instead of criteria, fetch partially the bids collections
List<Item> items = session.createQuery(
"from Item i left join fetch i.bids b where b.amount > :amount")
.setParameter("amount", 100)
.list();
It seems to me an inconsistency, but it's how this works
By the way, if what you need is the list of parents and all its children, but just the parents whose children all meet certain restriction, so you may use this
List<Item> items = session.createQuery(
"from Item i left join fetch i.bids b " +
"where not exists (from Bid b where b.item = i and b.amount <= :amount)")
.setParameter("amount", 100)
.list();
This is a related posts: Hibernate query not returning full object.
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