我有3个实体:' Person',' Document',' PersonDocument'其中涉及如下:
class Person {
@Cascade(CascadeType.ALL)
@OneToMany(mappedBy = "person", orphanRemoval = true, fetch = FetchType.LAZY)
Set<PersonDocument> personDocuments;
}
class Document {
@OneToMany(mappedBy = "document")
Set<PersonDocument> personDocuments;
}
@IdClass(PersonDocumentPK.class)
public class PersonDocument {
@Id
private Person person;
@Id
private Document document;
@ManyToOne(fetch = FetchType.LAZY)
private Provider provider;
}
public class PersonDocumentPK implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "person_guid")
private Person person;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "documents_guid")
private Document document;
}
在我的代码中,我尝试从Person#personDocuments
删除一些记录并添加新记录。我这样做:
Iterator it = person.getPersonDocuments().iterator();
PersonDocument pd = it.next();
if (some logic) it.remove();
...
person.getPersonDocuments().addAll(new set of values);
结果已移除personDocuments
已消失,但相关的documents
仍保留在数据库中。为什么会这样?
答案 0 :(得分:1)
级联操作不会那样。
当您使用@Cascade
注释时,在父级中进行的操作将级联到子级别,这取决于级联类型。
由于您的课程使用CascadeType.ALL
进行注释,因此在父课程中所做的所有操作将级联到子级。
因此,要使删除工作,您需要调用entityManager.remove(person)
,然后持久性提供程序也会调用子级中的删除。
话虽如此,将代码更改为类似的东西:
Iterator it = person.getPersonDocuments().iterator();
PersonDocument pd = it.next();
if (some logic) {
it.remove();
em.remove(pd); // No problem to call in the loop because it will call the database only on commit or flush
}
...
person.getPersonDocuments().addAll(new set of values);
答案 1 :(得分:0)
尝试 CascadeType.DELETE 而不是 CascadeType.ALL
@Cascade({CascadeType.SAVE_UPDATE,CascadeType.DELETE})