I have two entities joined by a bidirectional OneToOne-association like this:
@Entity
class Parent {
@NotNull
String businessKey;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "child_id")
@JsonManagedReference
Child child;
}
@Entity
class Child {
@JsonBackReference
@OneToOne(mappedBy = "child", fetch = FetchType.LAZY)
Parent parent;
}
Background
I'm using Spring Data and CRUDRepository to load the Parent using a generated Query like Parent findByBusinessKey(String businessKey)
because the default FetchMode is Eager the Child entity gets fetched by its child_id
foreign key in the Parent Table. Eager fetching is no Problm here, because the whole graph gets serialized to json later.
Originally the association was unidirectional and the Child had no reference to its Parent. Unfortunately the Back-reference had to be added and Performance degraded extremely. Logging of generated Sql showed the following Queries (simplified):
select p.id, p.business_key, ..., p.child_id from Parent p where p.business_key = ?;
select c.id, ... from Child c where c.id = ?;
-- here it goes wrong
select p.id, p.business_key, ... from Parent p
left join OtherEagerJoinedTable t on p.other_id = t.id
left join AnotherEagerJoinedTable a on p.another_id = a.id
where p.child_id = ?;
Hibernate seems to fetch the Parent separately from the Database instead of using the already selected instance. This happens for every OneToOne Relation like this (there are a few) with each join query taking up to 200 ms. With unidirectional Mapping the whole Entity Graph was queried in less than 100 ms.
Questions
How can i tell Hibernate that the Parent Entity already exists and the fetch is not needed? I tried optional=false
in Child entity but it didn't help.
Versions
I'm currently using hibernate 5.2.12 and Spring Boot 1.2.8. Unfortunately Update of Versions is currently not an option. Also even if changes on the DB side are still possible it would require relatively large refactoring effort in other places. I just need to tell hibernate not to eagerly fetch the parent reference from Db. Maybe an EntityGraph could help with that but I have not used them yet and now not much about it.
see also
- https://vladmihalcea.com/hibernate-facts-the-importance-of-fetch-strategy (the part Conclusion mentions the optional Attribute but the owning side in this example is inverted to my situation)
- Hibernate performs twice the same query if a bidirectional relationship is defined
- one to one mapping using primary key join column
- How can I make a JPA OneToOne relation lazy
Any help is appreciated