We are using Spring Data repositories with Hibernate 5.x
We have a entity graph with a deep hierarchy. The mapping looks like this:
@Entity
public class FooBar {
@OneToMany(mappedBy = "fooBar", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Foo> chassis = new HashSet<>(0);
...
}
@Entity
public class Foo {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "foobar_id")
private FooBar fooBar;
@OneToMany(mappedBy = "foo", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Bar> chassis = new HashSet<>(0);
...
}
@Entity
public class Bar {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "foo_id")
private FooBar foo;
...
}
As you can see the FooBar entity has a set of Foo entities. Each Foo entity contains more Bar entities and so on.
We use the Fetchgraph feature to load the FooBar entity with the relations we need during runtime to avoid n+1 query issue when fetching lazy associations. After the service call to load the entity graph the transaction has ended and the entity is detached.
When calling save on the FooBar entity at a later time, this causes multiple select statements. Each fetching one of the child entities.
I know that this comes from the entitymanager merge() call which fetches the object graph from the db before copying state changes from the detached objects.
I have two questions:
Why is hibernate not able to join these statements to one big select like what happens when using the fetchgraph?
When i remove all cascade options from the relations it still causes multiple selects but only attributes of the top, FooBar entity, will be updated. Why is hibernate still fetching all loaded child entites during merge even with no cascade merge?
Thanks