Search code examples
javahibernateormlazy-evaluationeager

Dynamic Eager & Lazy Loading in Hibernate


I'm new to Hibernate, but have plenty of experience with the Entity Framework in C#. One feature I love is the ability to dynamically decide what to load immediately in a query. For example, consider a One-to-Many relationship of Class and Student Entities.

On a "View Classes" page I can do this:

context.Configuration.EnableLazyLoading = true; //default option
List<Classes> classes = context.Classes.ToList();

Now I can happily just show the class info, without wasting resources gathering student data. ONLY when the user clicks the "View Classes with Rosters" do I do the following:

context.Configuration.EnableLazyLoading = true;
List<Classes> classes = context.Classes.Include(c => c.Students).ToList();

With that one statement, I was able to decide that in this particular situation, I want to grab all the info at once. Not two queries. Not one-hundred queries. Just one query. All despite loading only the classes a few seconds prior.

All of my reading on Hibernate explains how you can specify lazy="true|false" in the configuration files of relationships, but I really want the option of deciding when to load collections on the fly. After all, I'm not interested in buying a car that only goes either 30mph or 60mph. I need to choose a speed depending on where I am.

Perhaps the option of using fetch mode as JOIN is acceptable in that it will only be two queries in this situation (one for the class, and one for the students), but I really liked having the option of doing it all in one query, especially if I have several child collections to load and don't want to perform a query per relationship. I realize the all-at-once joins create extra data that needs to be streamed, but I'm surprised that this level of control isn't easily done or may be unavailable entirely.


Solution

  • Hibernate doesn't have very convienent ways for dynamic fetching. You can control it by

    1. Using Dynamic fetching via HQL queries with join fetch (as @ThibaultClement suggested).
    2. Using Dynamic association fetching with Criteria.setFetchMode().
    3. Using Dynamic fetching via profiles with the @FetchProfile annotation.

    You can refer HQL joined query to eager fetch a large number of relationships for additional thoughts too.