Help writing test case for lazy loading

I’m attempting to use hibernate-test-case-templates to ask a question about lazy loading behavior for entities. In the real application I have a Parent / Child entity relationship. I think I should be able to call child.parent.getId() and hibernate will not load the parent because that id is present as a foreign key on the child.

I’m getting a third behavior from this test case which is neither what I’m seeing in my app, nor what I expect to see.

@Test
void hhh123Test() throws Exception {
  EntityManager entityManager = entityManagerFactory.createEntityManager();
  entityManager.getTransaction().begin();

   Parent parent = new Parent();
   entityManager.persist(parent);

   Child child = new Child().setParent(parent);
   entityManager.persist(child);

   entityManager.getTransaction().commit();
   entityManager.close();

   // LOAD ------------------------------------------------------------------
   EntityManager entityManager2 = entityManagerFactory.createEntityManager();
   entityManager2.getTransaction().begin();

   Child loaded = entityManager2.find(Child.class, child.getId());

   System.out.println();

   Parent loadedParent = loaded.parent;
   long a = loadedParent.getId();

   entityManager2.getTransaction().commit();

   entityManager2.close();
 }

In the test case, when I load the Child entity, it also loads the parent before loaded.parent is accessed:

Hibernate: 
    select
        c1_0.id,
        c1_0.parent_id,
        c1_0.tenant_id 
    from
        Child c1_0 
    where
        c1_0.id=? 
        and c1_0.tenant_id = ?
Hibernate: 
    select
        p1_0.id,
        p1_0.tenant_id 
    from
        Parent p1_0 
    where
        p1_0.id=? 
        and p1_0.tenant_id = ?

Any ideas what’s going on here? Once I have this working as expected, I want to demonstrate that hibernate is loading the full Parent row to get the id when as far as I can tell from the documentation, it should not have to do that. Thanks!

There are various JPA compliance settings that are probably active when coding a JPAUnitTestCase that might affect the behavior. See JpaComplianceSettings. Most likely, it is the hibernate.jpa.compliance.proxy setting which affects your scenario.

After trial and error, I have an explanation for the behavior I observed. Even though I was observing the sql to load Parent from the find call, it was the presence of loaded.parent reference further down the method that caused the immediate sql query to load Parent. When I switch that to loaded.getParent(), the sql to load the parent is delayed until the Parent is actually accessed.

After loaded.getParent() is invoked, I get the sql to load the Parent immediately, so it does not seem to be using the proxy as I would expect. I even removed the @TenantId field completely to cut down on potential causes:

Hibernate: 
    select
        p1_0.id,
        p1_0.name 
    from
        Parent p1_0 
    where
        p1_0.id=?

This now matches the behavior I’m seeing in my app, but not the behavior I’ve read about online. For example:

I can not find the documentation from Hibernate directly addressing what should happen in this situation.

I suppose that your debugger is causing the loading. I tried your example and don’t see the SQL query that fetches Parent.

1 Like

Confirmed. That’s unfortunate I can’t use the debugger to check the behavior. Thank you!