我有一个非常简单的Spring Boot测试
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Bean
public CommandLineRunner demo(ParentRepository parentRepo, ChildRepository childRepo) {
return (args) -> {
Parent parent = new Parent("Father");
parent = parentRepo.save(parent);
childRepo.save(new Child("Father", "Jack"));
for (Child child : childRepo.findAll()) {
System.out.println(child);
}
parentRepo.findById(parent.getName()).ifPresent(p -> {
System.out.println(p);
1. p.getChildren().clear();//update child set parent_name=null NULL not allowed for column "PARENT_NAME";
2. p.setChildren(null); //A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: springtest.Parent.children
parentRepo.save(p);
});
for (Parent p : parentRepo.findAll()) {
System.out.println(p);
}
};
}
}
父实体
@Entity
public class Parent {
@Id
@Column(name = "NAME", nullable = false)
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "PARENT_NAME")
private Set<Child> children;
protected Parent() {}
public Parent(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Set<Child> getChildren() {
return children;
}
public void setChildren(Set<Child> children) {
this.children = children;
}
@Override
public String toString() {
return "Parent[name=" + name + ", children=" + children.size() + "]";
}
}
子实体
@Entity
public class Child {
@Id
@Column(name = "NAME", nullable = false)
private String name;
@Column(name = "PARENT_NAME", nullable = false)
private String parentName;
protected Child() {}
public Child(String parentName, String name) {
this.parentName = parentName;
this.name = name;
}
@Override
public String toString() {
return "Child[parentName=" + parentName + ", name=" + name + "]";
}
}
ParentRepository
public interface ParentRepository extends CrudRepository<Parent, String> {}
ChildRepository
public interface ChildRepository extends CrudRepository<Child, String> {}
我想从父实体中删除子代。链接使用单向,并且拥有实体是父级。我尝试调用1。getChildren().clear()
,但是休眠状态最终生成了一条更新语句,该语句将parent_name设置为null(而不是delete,其中parent_name =“ Father”),这违反了Child表中的不可为空的约束。
然后我尝试呼叫2。setChildren(null)
,这次它给出了异常A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance
。
您如何解决上述问题以使孩子撤离工作正常?
答案 0 :(得分:1)
作为拥有实体,“父母”应该是唯一修改外键的人。因此,我将从“ Child”中删除parentName。
所以我会这样更改它:
@Entity
public class Child {
@Id
@Column(name = "NAME", nullable = false)
private String name;
protected Child() {}
public Child(String name) {
this.name = name;
}
@Override
public String toString() {
return "Child[name=" + name + "]";
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Bean
public CommandLineRunner demo(ParentRepository parentRepo, ChildRepository childRepo) {
return (args) -> {
Parent parent = new Parent("Father");
parent.add(new Child("Jack"));
parent = parentRepo.save(parent); //the child is saved because of the cascading
for (Child child : childRepo.findAll()) {
System.out.println(child);
}
parentRepo.findById(parent.getName()).ifPresent(p -> {
System.out.println(p);
p.getChildren().clear();
parentRepo.save(p);
});
for (Parent p : parentRepo.findAll()) {
System.out.println(p);
}
};
}
}