A fetch plan specifies which entity associations and collections are loaded during a retrieval operation or later navigation. In JPA, mapping-level FetchType.LAZY and FetchType.EAGER settings establish a global default. A practical starting point is to map associations and collections lazily, then load more for operations that need it. section 12.1 section 12.4
The plan answers what to load; the fetch strategy answers how to load it. Lazy navigation can issue one SELECT for the initial items and another for each item's seller or bids collection—the n+1 selects problem. Eager loading may reduce query count but produce oversized results, particularly when several collections are joined. Choose overrides for the access pattern rather than making every collection eager. section 12.2 section 12.2.1
Ways to tailor a default plan include:
- Mapping-level FetchType.EAGER when an association must always be available, including after detachment. Once the persistence context is closed, an uninitialized lazy association cannot be loaded. section 12.1.3
- JPA entity graphs for a particular find() or query. A load graph treats listed attributes as eager and leaves unlisted attributes at their mapped defaults; named graphs and subgraphs can express reusable paths. Graphs control what loads, not how. section 12.3.2 section 12.3
- Hibernate fetch profiles for selectively overriding lazy mappings with JOIN eager fetching during a unit of work, or batch and subselect prefetching to reduce queries while retaining lazy mappings. section 12.3 section 12.2.4
Load sellers for an item list
Suppose an item-list operation reads every seller's username. With lazy seller mappings, selecting all items and then calling item.getSeller().getUsername() in a loop can trigger a SELECT per seller. An entity graph naming seller can instead be supplied as the javax.persistence.loadgraph hint; the illustrated query retrieves items and sellers together. Leave bids lazy if the operation never reads them. section 12.2.1 section 12.3.2
Path: Ch12/fetchloadgraph/src/test/java/com/manning/javapersistence/ch12 /fetchloadgraph/FetchLoadGraph.java Map<String, Object> properties = new HashMap<>(); properties.put( "javax.persistence.loadgraph", em.getEntityGraph("ItemSeller") ); Item item = em.find(Item.class, ITEM_ID, properties); // select i.*, u.* // from ITEM i // inner join USERS u on u.ID = i.SELLER_ID // where i.ID = ?
The named ItemSeller load graph is passed to find(); the accompanying SQL shows the seller joined to the requested item. section 12.3.2
