[hibernate-dev] HHH-11223 : Initialize bytecode enhanced lazy group using a single SQL statement

Gail Badner gbadner at redhat.com
Fri Mar 2 00:55:48 EST 2018


Hi,

Currently, when a lazy group is loaded that has associations, there are 2
SQL statements executed.

For example, suppose the DEFAULT lazy group contains the following:

* Order#customer is a lazy many-to-one association;

* Order#text is a lazy LOB.


When one of these properties is referenced, Hibernate loads both of them.


Currently, it takes 2 SQL statements to get the association loaded.


1) Loads #text and the FK value for #customer (select o.text, o.customer_id
from orders o where o.id = ?)

2) Loads the state for #customer (select ... from customers c where c.id =
?)


In other words, FetchMode.SELECT is used to load associations in a lazy
group.


HHH-11223 involves combining the 2 SQL statements into a single statement
using a join (i.e., using FetchMode.JOIN), but only when at least one of
the following is true:


* caching is disabled for the SessionFactory (e.g., hibernate.cache.use_sec
ond_level_cache=false;

* caching is not enabled for "get" operations (i.e.,
session.getCacheMode().isGetEnabled() == false);

* the associated entity type (and subclasses?) is not cached

HHH-11223 only mentions to-one associations, but I think collections in a
lazy group could also be loaded using a join as well.

I think I'm pretty close, but I need to do a lot more testing to ensure it
covers things like:

* lazy association in composite ID
* lazy association in an embeddable
* lazy association in a secondary table
* lazy association in a subclass
* too many bags

This is what I have implemented so far:
https://github.com/hibernate/hibernate-orm/pull/2170

At the moment, I'm not looking for a comprehensive review. I'm just looking
for a review of the overall design.

I don't want to get into the nitty-gritty here, but, basically, I've
created a new type of AbstractLoadPlanBasedEntityLoader, LazyGroupLoader,
which loads the lazy group properties into the existing entity.

If caching is disabled for the SessionFactory, then one loader is
constructed per lazy group, and associations will be loaded using
FetchMode.JOIN.

If caching is enabled for the SessionFactory, then 2 loaders are
constructed per lazy group. One loader is used when caching is enabled for
"get" operations (using Fetch.SELECT for cached associated
entities/collections; Fetch.JOIN for other associations). The other loader
is used when caching is disabled for "get" operations.

Here are some of the changes to the default behavior (described above) that
could be useful:

1) Change all associations in lazy groups to be loaded using
FetchMode.SELECT (as is currently done without the fix), or using
FetchMode.JOIN (regardless of caching). A new configuration property could
be added:

hibernate.bytecode.lazyGroup_association_fetchMode=(default | select | join
)

2) Allow the FetchMode to be configured for a particular lazy association.
According to the documentation [1], @Fetch can't be used for this because,
"... FetchMode.JOIN acts as a FetchType.EAGER strategy. Even if we mark the
association as FetchType.LAZY, the FetchMode.JOIN will load the association
eagerly."

A new annotation could be introduced: @LazyFetch.

Comments or suggestions?

Thanks,
Gail

[1] http://docs.jboss.org/hibernate/orm/5.2/userguide/
html_single/Hibernate_User_Guide.html#fetching-fetchmode-join


More information about the hibernate-dev mailing list