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


有没有人有解决此问题的方法: https://hibernate.atlassian.net/browse/HHH-9663

我也面临着类似的问题。当我在两个实体之间创建单向(无反向引用)一对一关系并将orphan remove属性设置为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;
  ...
}

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


8184
2017-07-17 07:21


起源



答案:


级联 只是有道理 实体状态转换 从一个传播的  到了 儿童。在您的情况下,父母实际上是这个协会的孩子(拥有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);

10
2017-07-17 08:27



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


答案:


级联 只是有道理 实体状态转换 从一个传播的  到了 儿童。在您的情况下,父母实际上是这个协会的孩子(拥有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);

10
2017-07-17 08:27



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