从OneToMany集合中删除Spring Data REST + JPA [不是所有者端] [英] Spring Data REST + JPA remove from OneToMany collection [not owner side]
问题描述
当前,当尝试更新不是拥有方的集合(关系)时,Spring Data JPA
+ Spring Data REST
(Hibernate
作为JPA
实现)存在一个问题(一个众所周知的问题). /p>
映射如下:
@Entity(name = Product.NAME)
public class Product {
...
@OneToMany(mappedBy = "baseProduct", fetch = FetchType.LAZY, targetEntity = Variant.class)
List<Variant> getVariants() {
...
以及另一种形式:
@Entity(name = Variant.NAME)
public class Variant extends Product {
...
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Product.class)
@JoinColumn(name = "baseproduct_id", referencedColumnName = "id")
Product getBaseProduct() {
...
}
如果仅使用Spring Data JPA
,则
在 Java 方面,一切都好,但是,如果您想通过更新其变体集合来更新产品"并发送PATCH
请求包含以下内容的 https://localhost:8112/storefront/rest/product/21394435410197232 仅新的收藏(3件中有2件):
{"variants":["22801810293768080","22801810293768096"]}
我没有例外或其他任何东西,但是由于拥有方是另一方,因此任何东西都不会保留,而我又得到了旧的3 items
.
我know
我可以通过设置
@JoinColumn(name = "baseproduct_id", referencedColumnName = "id")
在两侧上都没有使用mappedBy
,但是我听说有一个性能隐含性,我不确定它有多大(我们有100多个具有@OneToMany
的实体)而且我想知道是否可以通过@PreUpdate
侦听器或其他更好的解决方法?
您必须同步双向关联的两端,还必须添加orphanRemoval
和Cascade
.
因此,您的映射将变为:
@OneToMany(
mappedBy = "baseProduct",
fetch = FetchType.LAZY,
targetEntity = Variant.class
cascade = CascadeType.ALL,
orphanRemoval = true)
List<Variant> getVariants() {
以及两个添加/删除方法:
public void addVariant(Variant variant) {
getVariants().add(variant);
variant.setBaseProuct(this);
}
public void removeVariant(Variant variant) {
variant.setBaseProuct(null);
this.getVariants().remove(variant);
}
您需要实现 equals
和Variant子实体中的> hashCode
方法可以使add
和remove
方法有效地工作.
Currently we have an issue (a well known one) with Spring Data JPA
+ Spring Data REST
(Hibernate
as JPA
implementation) when trying to update the collection (relation) which is a not the owning side.
The mapping is the following:
@Entity(name = Product.NAME)
public class Product {
...
@OneToMany(mappedBy = "baseProduct", fetch = FetchType.LAZY, targetEntity = Variant.class)
List<Variant> getVariants() {
...
and on the other variant side:
@Entity(name = Variant.NAME)
public class Variant extends Product {
...
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Product.class)
@JoinColumn(name = "baseproduct_id", referencedColumnName = "id")
Product getBaseProduct() {
...
}
all is good on the Java side if you use Spring Data JPA
only, however if you want to update the "product" by updating its collection of variants and send PATCH
request to https://localhost:8112/storefront/rest/product/21394435410197232 containing the payload of the new collection only (having 2 out of the 3 items):
{"variants":["22801810293768080","22801810293768096"]}
I get no exceptions or anything but since the owning side is the other side nothing is persisted and I got the old 3 items
again.
I know
that I can fix this by setting
@JoinColumn(name = "baseproduct_id", referencedColumnName = "id")
on both sides and not use mappedBy
anywhere, however I have heard there is a performance implication which I am not sure how big it is (we got 100+ entities having @OneToMany
) and I wonder is there better workaround via @PreUpdate
listener or something ?
You have to synchronize both sides of the bidirectional association, and also add on orphanRemoval
and Cascade
.
So, your mapping becomes:
@OneToMany(
mappedBy = "baseProduct",
fetch = FetchType.LAZY,
targetEntity = Variant.class
cascade = CascadeType.ALL,
orphanRemoval = true)
List<Variant> getVariants() {
And the 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);
}
You need to implement equals
and hashCode
methods in the Variant
child entity for the add
and remove
methods to work effectively.
这篇关于从OneToMany集合中删除Spring Data REST + JPA [不是所有者端]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!