Fetch join using JPQL

Normally, we call the findById method of DAO to fetch the outer or parent entity and then call the getter methods of associations. Doing so leads to n + 1 queries because the framework will execute additional queries for each association. Instead, we can write a JPQL query using the createQuery method of EntityManager. In this query, we can join our associated entity, which we want to fetch along with the outer entity by using JOIN FETCH. The following is an example of how to get JOIN FETCH entities:

Query query = getEntityManager().createQuery("SELECT a FROM Account AS a JOIN FETCH a.transactions WHERE a.accountId=:accountId", Account.class);
query.setParameter("accountId", accountId);
return (Account)query.getSingleResult();

The following is the log that states that only one query is executed:

2018-03-14 22:19:29 DEBUG ConcurrentStatisticsImpl:394 - HHH000117: HQL: SELECT a FROM Account AS a JOIN FETCH a.transactions WHERE a.accountId=:accountId, time: 72ms, rows: 3
Transactions:::3
2018-03-14 22:19:29 INFO StatisticalLoggingSessionEventListener:258 - Session Metrics {
26342110 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
520204 nanoseconds spent preparing 1 JDBC statements;
4487788 nanoseconds spent executing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
13503978 nanoseconds spent executing 1 flushes (flushing a total of
4 entities and 1 collections);
56615 nanoseconds spent executing 1 partial-flushes (flushing a
total of 0 entities and 0 collections)
}

JOIN FETCH tells entityManager to load the selected entity, as well as the associated entity, in the same query.

The advantage of this approach is that Hibernate fetches everything within one query. From a performance point of view, this option is good, because everything is fetched in a single query instead of multiple queries. This reduces the round-trips to the database for each separate query.

The disadvantage of this approach is that we need to write additional code to execute the query. It's not an issue until we have a few associations or relations to fetch. But, it gets worse if the entity has many associations and we need to fetch different associations for each different use case. So, in order to fulfill each different use case, we need to write different queries with required associations. Too many different queries for each use case would be quite messy, and also difficult to maintain.

This option would be a good approach if the number of queries requiring different join fetch combinations was low. 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset