Hibernate Tips: How to initialize lazy relationships within a query


Take your skills to the next level!

The Persistence Hub is the place to be for every Java developer. It gives you access to all my premium video courses, 2 monthly Q&A calls, monthly coding challenges, a community of like-minded developers, and regular expert sessions.


Hibernate Tips is a series of posts in which I describe a quick and easy solution for common Hibernate questions. If you have a question you like me to answer, please leave a comment below.

Question:

How can I initialize a lazy relationship within a query to avoid LazyInitializationExceptions?

Solution:

Hibernate throws a LazyInitializationException if you try to use the attribute of a lazily fetched relationship outside of an active Hibernate Session.

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Author a = em.createQuery("SELECT a FROM Author a WHERE id = 1", Author.class).getSingleResult();

em.getTransaction().commit();
em.close();
	
log.info(a.getFirstName()+" "+a.getLastName()+" wrote "+a.getBooks().size()+" books.");

You can avoid that by initializing the relationship before you close the session. Hibernate and JPA support different ways to do that. The easiest one is a JOIN FETCH statement within a query, like the one in the following code snippet.

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Author a = em.createQuery("SELECT a FROM Author a JOIN FETCH a.books WHERE a.id = 1", Author.class).getSingleResult();

em.getTransaction().commit();
em.close();
	
log.info(a.getFirstName()+" "+a.getLastName()+" wrote "+a.getBooks().size()+" books.");

The additional FETCH  keyword tells Hibernate to not only join the entity for the query but also to fetch it from the database to initialize the attribute. This prevents LazyInitializationExceptions if you access the relationship attribute outside of an active Hibernate Session.

Learn more:

Join Fetch statements are only 1 option to initialize lazy relationships. Other interesting options are @NamedEntityGraphs and dynamic entity graphs which allow you to define a query independent graph of entities which shall be fetched with a query.

Initializing a required lazy relationship does not only prevent LazyInitializationExceptions, it also can improve the performance by avoiding n+1 select issues. I get into more details about that in this free mini-course and in the Hibernate Performance Tuning Online Training.

Hibernate Tips Book

Get more recipes like this one in my new book Hibernate Tips: More than 70 solutions to common Hibernate problems.

It gives you more than 70 ready-to-use recipes for topics like basic and advanced mappings, logging, Java 8 support, caching, and statically and dynamically defined queries.

Get it now!

Related Articles

Responses

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.