I have a parent entity with some children entities. When saving a new parent entity and its children entities, Spring is able to call persist
and I could see there are only some INSERT statements generated.
Problem is when I add some new children entities to an existing parent entity and save it, Spring calls merge
instead and what I found was there were some SELECT statements generated for those new children entities before their INSERT statements.
How to avoid these extra SELECT statements?
e.g.
@Entity
public class MyParent {
...
@OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade = CascadeType.ALL)
private Set<MyChild> children;
}
@Entity
public class MyChild {
...
}
and
MyParent myParent = buildNewParentAndChildren();
myParentRepository.save(myParent); // deep down calls persist(), generates INSERT only
but
MyParent myParent = myParentRepository.findById(1);
MyChild myChild = buildNewChild();
myParent.getMyChildren().add(myChild);
myParentRepository.save(myParent); // deep down calls merge(), generates SELECT and INSERT
CodePudding user response:
You're adding an element to a collection. This has to initialize the lazy collection - therefore you get your SELECT
.
Note, that you don't need to work with the collection at all in order to add the element. You're using an "inverse" mapping by declaring mappedBy = "myParent"
. This means that it's the child who's responsible for persisting the association with its parent.
So what you need is:
MyParent myParent = myParentRepository.findById(1);
MyChild myChild = buildNewChild();
myChild.setParent(myParent);
someRepository.persist(myChild)
Next time you select MyParent from a different Hibernate Session, you'll get your new element in the collection.
It makes sense to add to the collection only if you intend to work with that list in the same request. But that means you do need the SELECT
.
PS: If you get rid of Spring Data in favour of Hibernate Session or JPA EntityManager, you'd be able to eliminate SELECT
ing MyParent too by using session.load(1)
or entityManager.getRerence(1)
.
CodePudding user response:
You're using Set
of children. That's fine but by its definition it should check that the newly added child wasn't present at the collection before. Consider using List
instead.
Also, I would suggest to check how to implement equals() and hashCode() for the entity correctly.