JPA 孤儿删除不适用于 OneToOne 关系

Posted

技术标签:

【中文标题】JPA 孤儿删除不适用于 OneToOne 关系【英文标题】:JPA orphan removal does not work for OneToOne relations 【发布时间】:2015-10-06 20:31:59 【问题描述】:

是否有人对此问题有解决方法:https://hibernate.atlassian.net/browse/HHH-9663?

我也面临类似的问题。当我在两个实体之间创建单面(无反向引用)一对一关系并将孤儿删除属性设置为 true 时,将引用设置为 null 后,被引用的对象仍在数据库中。

这是示例域模型:

@Entity
public class Parent 
  ...
  @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
  @JoinColumn(name = "child_id")
  private Child child;
  ...


@Entity
public class Child 
  ...
  @Lob
   private byte[] data;
  ...

我目前正在通过手动删除孤儿来解决这个问题。

【问题讨论】:

【参考方案1】:

级联仅对从 Parent 传播到 Child 的实体状态转换有意义。在您的情况下,父级实际上是该关联的子级(具有 FK)。

尝试使用此映射:

@Entity
public class Parent 
  ...
  @OneToOne(
      fetch = FetchType.LAZY, 
      cascade = CascadeType.ALL, 
      orphanRemoval = true, 
      mappedBy = "parent"
  )
  private Child child;
  ...


@Entity
public class Child 

    @OneToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;

    ...
    @Lob
    private byte[] data;
    ...

要级联删除孤儿,您现在需要:

Parent parent = ...;
parent.getChild().setParent(null);
parent.setChild(null);

或者更好的是,在Parent 实体类中配置setChild 方法来设置两个关联:

public void setChild(Child child) 
    if (child == null) 
        if (this.child != null) 
            this.child.setParent(null);
        
    
    else 
        child.setParent(this);
    
    this.child = child;

【讨论】:

我试过了,它按照你的描述工作,但由于某种原因,我的延迟加载现在停止工作。我查看了生成的查询,我可以看到发生了两个选择调用,一个用于获取父级,另一个用于获取子级和父级。有什么想法吗? 二选表示 LAZY 工作。您可以使用 HQL/JPQL 查询 JOIN FETCH。 我的意思是当我做类似的事情时 - Parent result = repository.findOne(parent.getId())。我看到两个选择。只有当我做类似的事情时,我才会想到: result.getChild() - 我会看到第二个选择。这不是一个正确的假设吗? 这是因为 Hibernate 无法知道关联是否为空,所以需要第二次查询。为避免这种情况,如果 FK 不为 NULL,您需要指定 optional=true。否则你需要使用延迟初始化和字节码增强。 你的意思是 - “可选=假”?我添加了:@OneToOne(optional = false) @JoinColumn(name = "parent_id") private Parent parent;

以上是关于JPA 孤儿删除不适用于 OneToOne 关系的主要内容,如果未能解决你的问题,请参考以下文章

Spring JPA 删除 @OneToOne 关系

在我的 Play 应用程序中使用 Ebean/JPA,如何删除 OneToOne 关系中的对象?

Spring Data+JPA:对 OneToOne 关系强制执行内部联接

JPA 2 / Hibernate 孤儿删除仍然无法与@OneToMany 一起使用?

JPA:OneToOne 关系所有者

hibernate/jpa double OneToOne 与一个实体的双向关系