JPA Pitfalls (12): Lazy Loading of Relationships in a Loop

This blog article is part of a “series of blog articles” about common pitfalls using JPA and ways to avoid them. In this article, we describe a potential performance problem when loading relationships in a loop.

The following code pattern easily runs into performance problems. It retrieves a list of entity instances from the database and for each entity accesses a number of attributes including lazy loaded relationships.

List<Employee> emps = // Retrieve employees from DB
for (Employee e : emps) {
        e.getFirstname(), e.getLastname(),
        e.getDepartment() == null ? 
            e.getDepartment().getName() : null,
        e.getInsurance() == null ? 
            e.getInsurance().getCarrier() : null);

In case the relationships department and insurance in Employee are defined as lazy loaded, each iteration will execute two database queries.

It is better to load all the required data with a single database query. The query does not return entities, instead it retrieves just the required fields and navigates the relationships as part of the query:

List<Object[]> empDetails = em.createQuery(
    "SELECT e.firstname, e.lastname,, i.carrier " +
    "FROM Employee e LEFT OUTER JOIN e.department d " + 
    "LEFT OUTER JOIN i").getResultList();
for (Object[] empDetail : empDetails) {
    showEmployeeDetails(empDetail[0], empDetail[1], 
                       empDetail[2], empDetail[3]);

Recommendation: Use a JPQL query to load specific fields including fields of associated entities.

You can find an example of this pitfall and its solution in the class LoadingRelationshipsExperiment in this project:

Leave a Reply