Spring Data REST + JPA remove from OneToMany collection [non-owner side]

We currently have a problem (well known) with Spring Data JPA + Spring Data REST ( Hibernate as a JPA implementation) when trying to update a collection (relation) that is not the owner side.

The display is as follows:

 @Entity(name = Product.NAME) public class Product { ... @OneToMany(mappedBy = "baseProduct", fetch = FetchType.LAZY, targetEntity = Variant.class) List<Variant> getVariants() { ... 

and on the other hand the options:

 @Entity(name = Variant.NAME) public class Variant extends Product { ... @ManyToOne(fetch = FetchType.LAZY, targetEntity = Product.class) @JoinColumn(name = "baseproduct_id", referencedColumnName = "id") Product getBaseProduct() { ... } 

everything is fine on the Java side if you use only Spring Data JPA , however, if you want to update the "product" by updating your collection of options and sending PATCH request https: // localhost: 8112 / storefront / rest / product / 21394435410197232 , which contains a useful the load of only the new collection (with two of the three elements):

 {"variants":["22801810293768080","22801810293768096"]} 

I don't get any exceptions or anything else, but since the owner side is the other side, nothing is saved, and again I got the old 3 items .

I know that I can fix this by setting

 @JoinColumn(name = "baseproduct_id", referencedColumnName = "id") 

on both sides and do not use mappedBy anywhere, however I heard that there are performance implications that I'm not sure how big they are (we got more than 100 objects with @OneToMany ). and I am wondering if there is a better workaround through @PreUpdate listener or something like that?

+8
java spring spring-data-jpa hibernate jpa
source share
1 answer

As explained in this article , you need to synchronize both sides of the bidirectional association, as well as add to orphanRemoval and Cascade.

So your mapping will look like this:

 @OneToMany( mappedBy = "baseProduct", fetch = FetchType.LAZY, targetEntity = Variant.class cascade = CascadeType.ALL, orphanRemoval = true) List<Variant> getVariants() { 

And two add / remove methods:

 public void addVariant(Variant variant) { getVariants().add(variant); variant.setBaseProuct(this); } public void removeVariant(Variant variant) { variant.setBaseProuct(null); this.getVariants().remove(variant); } 

For the removal method to work correctly, you need to implement equals and hashCode as explained in this article .

+5
source share

All Articles