JQPL query hydrates the entity with lazy collection

I have two entities called ConfigContainer and Configs. A ConfigContainer can have multiple Configs i.e the association b/w ConfigContainer and Configs is one-to-many.

When the following code inside a method is run:

  List<ConfigContainer> doConfigContainerQuery(
      ConfigContainerType containerType) {

    TypedQuery<DbConfigContainer> query = entityManager.createQuery(
        "SELECT cc FROM " +
            ConfigContainer.class.getName() +
            " cc WHERE cc.configType = :configType", ConfigContainer.class);

    query.setParameter("configType", containerType.toString());
    return query.getResultList();
  }

I see that the Configs are also brought into memory as well even though its fetch type is lazy!

As you can see the Entity which is ConfigContainer gets hydrated with Configs which is at index = 2. Right now this is a dummy environment so the size is only 32 but in a production environment the size of Configs collection can be HUGE!

In our production environment, the above code is a hotspot and gets executed a lot of the times.
We are currently facing performance issues. We found this as one of the culprit.

We are observing this only in our other JPQL queries. Like whenever a JPQL for an entity is executed, the entity gets hydrated with lazy associations.

On the contrary, there is this other scenario where the lazy association is working correctly.
The following is the EntityModel, where entity Foo is associated to ConfigContainer as many-to-one

Foo - (many-to-one) -> ConfigContainer -> (one-to-many) -> Config

When the code called Foo.getConfigsMap() it first calls configContainer and then the configContainer gets its configs.
The following is the method present in Foo.

getConfigsMaps() {
   List<Config> configs =   getConfigContainer().getImmutableConfigs();  // <-- breakpoint here.
   // some logic
}

If I debug at the above line on the getConfigContainer() part, That time configs are not loaded. See the index = 2

 hydratedState = {Object[4] @35594} {
      0 = {Long@35249} 33
      1 = "configType"
      2 = {PersistentSet@35535} Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception.
      3 = (Long@35396} 11
} 

Why is the Entity of ConfigContainer getting hydrated with the lazy collection?
Is there a way to avoid this ?

Hibernate Version: 5.4

It’s the fault of your debugger, because it calls toString() on the PersistentSet, which causes it to initialize. You can configure your debugger to use a different representation for objects that implement PersistentCollection though. See Setting up IntelliJ IDEA to contribute to Hibernate projects - Hibernate for details.

1 Like

Thanks @beikov . After incorporating the above change, when I debug now, I can see the above collection as uninitialized.

But in the logs we are seeing intermitent N calls to Configs when I fetch the ConfigContainer by type and perform getImmutableConfigs() on it.

ConfigContainer cc =. getConfigContainerByType(configType);
cc.getImmutableConfigs();

This is happening after we upgraded Hibernate version from 5.2.4.Final to 5.4.27.Final due to CVE. A pom.xml file change. We made the following changes:

We kept Hibernate-validator at 5.2.4.Final
and upgraded hibernate-core, hibernate-entitymanager, hibernate-c3p0, hibernate-ehcache, hibernate-envers to 5.4.27.Final
We kept the hibernate-jpa-2.1-api at 1.0.0.Final

Hibernate 5.2.4.Final: (Only two SQLs)

select ... from CONFIG_CONTAINER where configType=?
select ... from CONFIG where  CONFIG_CONTAINER_ID=?

Hibernate 5.4.27.Final: (N calls to Configs)

select ... from CONFIG_CONTAINER where  CONFIG_TYPE=?

select ... from CONFIG where CONFIG_ID=?
.
.
N Calls to configs
.
select ... from CONFIG where CONFIG_ID=?

These entities and few others similar to these ones are hotspots in our code and are executed numerous times. After upgradation, wee are observing slowness.

We are wondering what changed from 5.2 → 5.4 ? Any guidance would be really helpful!
Currently we are upgrading to 5.3 to check whether we the performance issuee or not.

If this can’t be answered here then I will raise a separate post.

I have no idea what your code is doing, but these kinds of queries (primary key lookup) usually happens when doing lazy initialization of an entity proxy. You can set a break point into org.hibernate.resource.jdbc.internal.EmptyStatementInspector#inspect to see what triggers the lazy initialization. Either way, if you need further help after analyzing this, please create a new topic and share code as well as logs in a way, that assumes I have never heard of your problem, as I tend to forget stuff and guessing stuff from examples your gave is really hard and time consuming.