TLDR:将休眠版本从 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:这是我的第一个问题,如果需要更多信息,或者配方有问题,请告诉我。:)