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 关系的主要内容,如果未能解决你的问题,请参考以下文章
在我的 Play 应用程序中使用 Ebean/JPA,如何删除 OneToOne 关系中的对象?
Spring Data+JPA:对 OneToOne 关系强制执行内部联接