By default, Hibernate never loads data that you didn’t ask for, which reduces the memory consumption of your persistence context.
Instead of executing too many SQL statements (N+1), you may now (often as a side effect) create statements that retrieve too much data (always using one query to initialize all list).
<class name="Item">To avoid n+1 selects, a first solution could be a change of your global mapping metadata for the collection,enabling prefetching in batches:
...
<set name="bids" inverse="true">
<key column="ITEM_ID">
<one-to-many class="Bid">
</set>
</class>
<set name="bids" inverse="true" batch-size="10">Instead of n+1 selects, you now see n/10+1 selects to retrieve the required collections into memory.
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
With a subselect-based prefetch, you can reduce the number of selects to exactly two:
<set name="bids" inverse="true" fetch="subselect">The first query in the procedure now executes a single SQL SELECT to retrieve all Item instances. Hibernate remembers this statement and applies it again when you hit the first uninitialized collection. All collections are initialized with the second query.
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
Finally, you can effectively turn off lazy loading of the bids collection and switch to an eager fetching strategy that results in only a single SQL SELECT.
<set name="bids" inverse="true" fetch="join">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
In practice, you’ll most likely enable a batch or subselect strategy in your mapping metadata for the bids collection. If a particular procedure, such as this,requires all the bids for each Item in-memory, you modify the initial HQL or Criteria query and apply a dynamic fetching strategy:
List<Item> allItems = session.createQuery("from Item i left join fetch i.bids").list();
List<Item> allItems = session.createCriteria(Item.class)
.setFetchMode("bids", FetchMode.JOIN).list();
// Iterate through the collections...
Both queries result in a single SELECT that retrieves the bids for all Item instances with an OUTER JOIN (as it would if you have mapped the collection with join="fetch").
-- excerpted from Java.Persistence.with.Hibernate
No comments:
Post a Comment