【问题标题】:JPA orphan removal does not work for OneToOne relationsJPA 孤儿删除不适用于 OneToOne 关系
【发布时间】: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;
  ...
}

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

【问题讨论】:

    标签: java hibernate jpa orm spring-data-jpa


    【解决方案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;
    猜你喜欢
    • 2010-09-23
    • 2011-02-09
    • 2013-06-05
    • 2018-03-31
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多