Java 休眠级联删除不';行不通

Java 休眠级联删除不';行不通,java,hibernate,cascade,Java,Hibernate,Cascade,我有3个实体:“个人”、“文件”、“个人文件”,其相关内容如下: class Person { @Cascade(CascadeType.ALL) @OneToMany(mappedBy = "person", orphanRemoval = true, fetch = FetchType.LAZY) Set<PersonDocument> personDocuments; } class Document { @OneToMany(mappedBy

我有3个实体:“个人”、“文件”、“个人文件”,其相关内容如下:

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;
}

结果删除的
个人文档
已经消失,但相关的
文档
仍保留在数据库中。为什么会这样?

尝试级联类型。删除而不是级联类型。全部


@级联({CascadeType.SAVE\u UPDATE,CascadeType.DELETE})

级联操作不是这样工作的

使用
@Cascade
注释时,在父对象中执行的操作将根据级联类型级联到子对象

由于您的类是用
CascadeType.ALL
注释的,因此父类中的所有操作都将级联到子类

因此,要使删除生效,您需要调用
entityManager.remove(person)
,然后持久性提供程序也会在child中调用删除

也就是说,将您的代码更改为:

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);   

在本例中,我遇到了异常:
model.entity.PersonDocument实例的标识符已从model.entity更改。PersonDocumentPK@f224a1f1对实体进行建模。PersonDocumentPK@de57b5f
您可以看到mkyoung示例,还可以从mysqlWorkbech中删除cascade直接地
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);