【发布时间】:2013-07-25 01:42:35
【问题描述】:
我有两个具有一对一关系的实体,A 和 B。B 实体是可选的,可以自行更新和删除,但必须始终链接到 A 的实例。
所以我有两个具有双向关系的 JPA 实体 A 和 B。这是从 A 到 B 的那个。
@OneToOne(mappedBy = "a", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
我可以创建 A 和 B,删除 A 并同时删除。不错。
但是由于从 A 到 B 的级联,如果我 em.remove(b) 删除不会被持久化。即使我先做a.setB(null)。
在保持级联的同时删除可选实体的唯一方法似乎是使用新的 JPA2 功能,orphanRemoval=true。调用a.setB(null),然后坚持A。
这意味着我不能直接对B进行操作,这意味着组合关系太强,所有对B的操作都必须通过A完成。
但是 B 不是嵌入式对象,它本身就是一个成熟的实体,我怎样才能独立于 A 删除它?
最好的方法似乎是删除级联,并强制用户确保在删除 A 之前单独删除任何相关对象?由 B 表中的 FK 约束强制执行。
这是一个直截了当的案例。两个相关实体,这种关系一方面是可选的,另一方面是强制性的。
哦,这里是hibernate 4.2.3-Final
【问题讨论】:
-
em.remove(b)应该可以工作,无论您在 A 上是否有任何级联。您是否尝试过一个简单的示例,您只需打开一个事务,找到 B 的一个实例,对其调用 remove,然后提交事务?只是出于好奇,您是否在删除之前将 B 对 A 的引用设置为 null?我认为您不必这样做,但这可能会有所作为。 -
嗨,是的,我试过了。刚刚尝试将 Bs 对 A 的引用也设置为 null 并且没有更改。但是,在我删除之后和我找到之前,我只是尝试在 EntityManager 上调用flush。现在它似乎被删除了。所以看起来像一个休眠缓存错误?
-
您是否将刷新模式更改为 FlushMode.AUTO 以外的其他模式?如果是这样,那不是缓存错误,这就是 Hibernate 的设计方式。
-
不,我没有'改变冲洗模式。 Hibernate 旨在从查找中返回陈旧数据?它打破了基本的事务语义。你有这方面的参考吗?
-
如果刷新模式不在 FlushMode.AUTO 上,那么 Hibernate 在查询之前不会刷新。当您修改实体时,该修改不会立即推送到数据库。相反,所有修改都会在下一次刷新时推送到数据库。使用 FlushMode.AUTO Hibernate 将在任何不是基本查找查询的查询之前将所有内容刷新到数据库中。许多人禁用此功能,因为如果您执行大量查询并且您知道自己没有修改数据,它会降低性能。