Thanks for the help understanding the behavior in my test case: Help writing test case for lazy loading - #5 by kevinm416 . Now that I understand the baseline behavior I can ask my real question.
I have Parent + Child entities and a ParentId typed id that I want to use to wrap Parent’s id for type safety.
I’ve updated my test case: Lazy-loading issue by kevinm416 · Pull Request #607 · hibernate/hibernate-test-case-templates · GitHub .
@Entity
public class Child {
@Id
@GeneratedValue
long id;
@TenantId
@Column(name = "tenant_id", nullable = false, updatable = false)
private Long tenantId;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "parent_id", nullable = false)
public Parent parent;
...
@Entity
public class Parent {
@Id
@GeneratedValue
long id;
@Column
String name;
@TenantId
@Column(name = "tenant_id", nullable = false, updatable = false)
private Long tenantId;
public long getId() {
return id;
}
public ParentId getTypedId() {
return new ParentId(getId());
}
}
public class ParentId {
private final long id;
public ParentId(long id) {
this.id = id;
}
}
The test loads a Child, and then accesses child.getParent().getTypedId():
@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();
ParentId parentId = loaded.getParent().getTypedId(); // <---- Parent entity sql load
System.out.println(parentId);
entityManager2.getTransaction().commit();
entityManager2.close();
}
I’ve tried various different variations, like Hibernate annotations on methods vs fields and accessing the id field directly vs using getId(). In all situations that I tried, calling getTypedId() loads the Parent entity, and calling getId() does not.
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.name,
p1_0.tenant_id
from
Parent p1_0
where
p1_0.id=?
and p1_0.tenant_id = ?
Is there a way I can avoid this load and keep my getTypedId() method?
It seems like this should be possible, since the instance method getTypedId() is equivalent to this static method, which does not load the Parent from the DB:
public static ParentId getParentId(Parent parent) {
return new ParentId(parent.get());
}