Spring 数据 JPA - ManyToOne 无法在不修改 parent 列表的情况下删除 child
Spring Data JPA - ManyToOne unable to delete child without modifying parent list
我与以下问题斗争了一个星期:
如何在不修改关系的拥有 (parent) 端的列表的情况下通过存储库删除 child 实体?
提前致谢。
我希望得到一些答案!
childclass:
@Entity
@Table(name = "child")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@ManyToOne
private Parent parent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
还有 parent class:
@Entity
@Table(name = "parent")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Parent implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnore
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Child> children = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
public Parent addChild(Child child) {
this.children.add(child);
child.setParent(this);
return this;
}
public Parent removeChild(Child child) {
this.children.remove(child);
child.setParent(null);
return this;
}
}
这里是测试:
@Test
@Transactional
public void testParentToChildRelationShip() {
Parent parent = new Parent();
Child child = new Child();
parent.addChild(child);
parent.addChild(new Child());
parent.addChild(new Child());
parent.addChild(new Child());
parentRepository.save(parent);
Assertions.assertThat(parentRepository.count()).isEqualTo(1L);
Assertions.assertThat(childRepository.count()).isEqualTo(4L);
childRepository.delete(child);
Assertions.assertThat(parentRepository.count()).isEqualTo(1L);
// fails
Assertions.assertThat(childRepository.count()).isEqualTo(3L);
parentRepository.delete(parent.getId());
Assertions.assertThat(parentRepository.count()).isEqualTo(0L);
Assertions.assertThat(childRepository.count()).isEqualTo(0L);
}
如果我在删除 child、
之前插入,测试将有效
child.getParent().removeChild(child);
但我想避免这样调用。
有没有办法让它只调用 Child-JPA-Repository.delete 方法就可以工作?或者我错过的其他注释?
由于 child
与 parent
有关联,您正面临此问题,您需要使用
删除子项和父项之间的 link
parent.removeChild(child);
或
child.getParent().removeChild(child);
从 parent class 以及 children
的 setter 和 getter 中删除这些行
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnore
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Child> children = new HashSet<>();
我认为您可以从 parent class
中删除 child mapping
,这样您就可以使用 ChildRepository
delete()
方法轻松删除 child 行,但问题是您必须使用 ChildRepository
save()
保存您的 child manually
。您不能使用 ParentRepository
保存 child object 和 parent object。像下面这样更改您的 Test 代码以保存 child
和 parent
Parent parent = new Parent();
Parent parent = parentRepository.save(parent);
Child child = new Child();
child.setParent(parent);
childRepository.save(child);
我与以下问题斗争了一个星期:
如何在不修改关系的拥有 (parent) 端的列表的情况下通过存储库删除 child 实体?
提前致谢。
我希望得到一些答案!
childclass:
@Entity
@Table(name = "child")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Child implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@ManyToOne
private Parent parent;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
}
还有 parent class:
@Entity
@Table(name = "parent")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Parent implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnore
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Child> children = new HashSet<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
public Parent addChild(Child child) {
this.children.add(child);
child.setParent(this);
return this;
}
public Parent removeChild(Child child) {
this.children.remove(child);
child.setParent(null);
return this;
}
}
这里是测试:
@Test
@Transactional
public void testParentToChildRelationShip() {
Parent parent = new Parent();
Child child = new Child();
parent.addChild(child);
parent.addChild(new Child());
parent.addChild(new Child());
parent.addChild(new Child());
parentRepository.save(parent);
Assertions.assertThat(parentRepository.count()).isEqualTo(1L);
Assertions.assertThat(childRepository.count()).isEqualTo(4L);
childRepository.delete(child);
Assertions.assertThat(parentRepository.count()).isEqualTo(1L);
// fails
Assertions.assertThat(childRepository.count()).isEqualTo(3L);
parentRepository.delete(parent.getId());
Assertions.assertThat(parentRepository.count()).isEqualTo(0L);
Assertions.assertThat(childRepository.count()).isEqualTo(0L);
}
如果我在删除 child、
之前插入,测试将有效child.getParent().removeChild(child);
但我想避免这样调用。 有没有办法让它只调用 Child-JPA-Repository.delete 方法就可以工作?或者我错过的其他注释?
由于 child
与 parent
有关联,您正面临此问题,您需要使用
parent.removeChild(child);
或
child.getParent().removeChild(child);
从 parent class 以及 children
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonIgnore
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<Child> children = new HashSet<>();
我认为您可以从 parent class
中删除 child mapping
,这样您就可以使用 ChildRepository
delete()
方法轻松删除 child 行,但问题是您必须使用 ChildRepository
save()
保存您的 child manually
。您不能使用 ParentRepository
保存 child object 和 parent object。像下面这样更改您的 Test 代码以保存 child
和 parent
Parent parent = new Parent();
Parent parent = parentRepository.save(parent);
Child child = new Child();
child.setParent(parent);
childRepository.save(child);