如何确保休眠 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 在与共享主键的一对一关系中保持正确的顺序的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 或实体框架中创建没有主键的一对多关系?

MySQL 基础

没有主键或连接表的休眠多对一关系

SQLAlchemy(三):外键连表关系

创建一对一关系的表

EF 6.1 Code First 中与不同主键的一对一关系