27/09/2024

[Java] Load entity with lazy children collections

When using JPA and lazy collection loading, at the time the parent entity is retrieved from DB, the lazy children are NOT also loaded in memory, instead, a proxy reference is added, which is used to retrieve the data if that particular field is ever accessed.

In some scenarios you might want to load the whole entity, including the lazy children in memory instead (eg you want to clone/serialize it, whatever).


If you want to load ONE child together with the parent, a JOIN FETCH clause would do the trick: 

SELECT p

FROM Parent p

LEFT JOIN FETCH p.childField c

WHERE p.id = :id


But if you try to load more than one child at the same time, you will get a MultipleBagFetchException. A workaround is to call the load with JOIN FETCH for all entities you need sequentially, for example:

private Parent loadChildViaQuery(ID id, String childClause) {
  return entityManager
    .createQuery(
      "select p " +
      "from Parent p " +
      "left join fetch " +
      childClause +
      " where p.id = :id",
      Parent.class
    )
    .setParameter("id", id)
    .getSingleResult();
}

Where childClause input is the join statement you need, for example:

"p.childField c"

Also remember that if the parent entity is not found, the operation would throw a NoResultException, while if the child is not found, no exception is raised, the child is simply null/empty.

No comments:

Post a Comment

With great power comes great responsibility