无法删除作为@OneToOne关系目标的实体

amo*_*fis 4 java hibernate jpa

我有@OneToOne关系的以下实体:

@Entity
public static class EntityChild extends BaseEntity {
    //Id from superclass
}

@Entity
public static class EntityParent extends BaseEntity {

    //Id from superclass

    @OneToOne(cascade = ALL)
    private EntityChild child;

    //child getter/setter
}
Run Code Online (Sandbox Code Playgroud)

现在以下测试没有通过:

EntityParent parent = new EntityParent();
em.persist(parent);
em.flush();

EntityChild child = new EntityChild();
parent.setChild(child);
em.persist(parent);
em.flush();

em.remove(parent.getChild());
em.flush();
Run Code Online (Sandbox Code Playgroud)

它使用flush()在最后一行抛出异常.例外是javax.persistence.EntityNotFoundException: deleted entity passed to persist: [my.package.EntityChild#<null>]

为什么我不能删除这个实体?

axt*_*avt 5

您需要首先删除父级和子级之间的关联,否则Hibernate会尝试再次保留该子级,原因cascade = ALL如下:

EntityChild c = parent.getChild();
parent.setChild(null);
em.remove(c);
em.flush(); 
Run Code Online (Sandbox Code Playgroud)

更新:

以下是与此行为相关的JPA规范的摘录.由于[1]和[2]之间的冲突而引发异常flush()(尽管我找不到它指定的位置):

应用于实体X 的刷新操作的语义如下:

  • 如果X是托管实体,则会将其同步到数据库.

    • 通过从X的关系中引用的所有实体Y,如果Y的关系已经被注释与所述cascade元素值cascade=PERSISTcascade=ALL,persist操作被施加到Y.

    • 对于由X的关系引用的任何实体Y,其中与Y的关系未使用cascade元素值注释cascade=PERSISTcascade= ALL:

      • 如果Y是新的或被删除,IllegalStateException则刷新操作(以及标记为回滚的事务)将抛出一个或者事务提交将失败.

      • 如果分离Y,则语义取决于关系的所有权.如果X拥有该关系,则对该关系的任何更改都将与数据库同步; 否则,如果Y拥有关系,则行为未定义.

  • 如果X是已删除的实体,则会从数据库中删除它.没有级联选项是相关的.<--------------- [1]


应用于实体X 的持久化操作的语义如下:

  • 如果X是一个新实体,它就会被管理.实体X将在事务提交时或之前或作为刷新操作的结果输入数据库.

  • 如果X是预先存在的托管实体,则persist操作会忽略它.但是,如果从X到这些其他实体的关系使用cascade=PERSISTcascade=ALL 注释元素值注释或使用等效的XML描述符元素指定,则持久化操作将级联到X引用的实体 .

  • 如果X是已删除的实体,则它将被管理.<--------------- [2]

  • 如果X是一个分离的对象,则 EntityExistsException可以在调用持久化操作时抛出,或者可以在刷新或提交时抛出该EntityExistsException另一个或另一个PersistenceException.

  • 通过从X的关系中引用的所有实体Y,如果Y的关系已经被注释与级联元件值 cascade=PERSISTcascade=ALL,persist操作被施加到Y.