如何确保休眠 5 在与共享主键的一对一关系中保持正确的顺序
Posted
技术标签:
【中文标题】如何确保休眠 5 在与共享主键的一对一关系中保持正确的顺序【英文标题】:How to make sure hibernate 5 persists in the correct order in a one-to-one relationship with shared primary key 【发布时间】:2020-02-06 11:09:58 【问题描述】:TLDR:将 Hibernate 版本从 3. 切换到 5.。现在,与仅在一个类中映射的共享主键的 OneToOne 关系以错误的顺序保留两个实体,违反了外键约束。如何更改订单?
在从 jboss 7 实例迁移到当前 wildfly 的过程中,我的团队还必须将我们的休眠版本从 3 更新到 5.3.10。
在执行此操作时,我遇到了一个实体构造问题,我在其中遇到了问题。
一般概念如下:
我有一个主实体类,它有多个“模块”作为属性,它们共享主实体类的主键。这些模块本身就是实体类,并拥有各种逻辑和进一步的关系。但是,模块实体没有任何其他持久属性。它们也没有对主要实体类的引用。
在这方面,它是(在 Java 的面向对象世界中)与共享主键的单向关系(我理解共享主键使其对数据库是双向的)。
Java 代码应该是这样的:
@Entity(name = "mainEntity")
@Table(name = "main_entity")
public class MainEntity
// Business Logic ...
@Id
private Long id;
@OneToOne( targetEntity = ModuleA.class, cascade = CascadeType.ALL, optional = false,
orphanRemoval = true )
@PrimaryKeyJoinColumn( name = "id", referencedColumnName = "id" )
private ModuleA moduleA;
// More Modules...
@Entity(name=moduleA)
@Table(name=module_a)
public class ModuleA
@Id
private Long id;
// other relationships to entirely different entities,
// but no reference to mainEntity or other "modules"
在我们以前的系统中,这工作得很好。当使用类似
entityManager.persist(mainEntity);
模块将首先被持久化,然后是 mainEntity。
但是,在我们更新的休眠版本中,情况并非如此。 使用这个映射,插入顺序被颠倒,entityManager 将首先尝试持久化 mainEntity。这会导致违反应防止表之间不一致的外键约束。
附带说明:我尝试改变
@PrimaryKeyJoinColumn(...)
进入
@MapsId(value="id")
这实际上正确地改变了持久性顺序。但是,这样做会导致休眠不再正确理解共享主键 -> 虽然由于某种原因持久化工作,
entityManager.find(ModuleA.class,primaryKey);
没有工作,产生诸如“列 mainEntity.moduleA_id 不存在”之类的错误。
您是否可以想出一种方法来表达需要先持久化模块,就像 Hibernate 3 为我们所做的那样?
我将非常感谢任何帮助。
PS:这是我的第一个问题,如果需要更多信息,或者配方有问题,请告诉我。 :)
【问题讨论】:
【参考方案1】:好的,经过一些分析,我想分享一下我们对此做了什么。
首先,问题中提供的映射适用于 Hibernate 3.6.10.Final 直到 Hibernate 5.2.13.Final 开始失败。奇怪的是,从 5.4.0.CR1 开始,它又开始工作了。
我们还没有找到在约束到位的情况下继续使用此映射的方法。 在我们的例子中,我们认为约束不值得麻烦,但是为了更可靠地映射这种事情,我们发现使用 @MapsId 更成功。在那里,模块需要对 MainEntity 的引用,并在其上使用 @MapsId 来派生其 id。
【讨论】:
以上是关于如何确保休眠 5 在与共享主键的一对一关系中保持正确的顺序的主要内容,如果未能解决你的问题,请参考以下文章