TLDR:将休眠版本从3.切换到5.。现在,与仅在一个类中映射的共享主键的一对一关系以错误的顺序保留两个实体,从而违反了外键约束。如何更改订单?
在从 jboss 7 实例迁移到当前野蝇的过程中,我的团队还必须将休眠版本从 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);
模块将首先持久化,然后持久化主实体。
但是,对于我们更新的休眠版本,情况并非如此。 使用此映射,广告顺序颠倒,实体管理器将首先尝试保留主实体。这会导致违反外键约束,该约束应防止表之间的不一致。
附带说明:我尝试更改
@PrimaryKeyJoinColumn(...)
到
@MapsId(value="id")
这实际上正确地改变了坚持顺序。但是,这样做会导致休眠不再正确理解共享主键 -> 虽然由于某种原因坚持工作,
entityManager.find(ModuleA.class,primaryKey);
不起作用,产生诸如"列mainEntity.moduleA_id不存在"之类的错误。
有没有办法表达首先持久化模块的必要性,就像Hibernate 3为我们所做的那样?
我将非常感谢任何帮助。
PS:这是我的第一个问题,如果需要更多信息,或者配方有问题,请告诉。 :)
好的,经过一些分析,我想分享我们对此所做的工作。
首先,问题中提供的映射适用于Hibernate 3.6.10.Final,直到Hibernate 5.2.13.Final开始失败。奇怪的是,从 5.4.0.CR1 开始,它又开始工作了。
我们还没有找到在约束就位的情况下继续使用此映射的方法。 在我们的例子中,我们认为约束不值得麻烦,但为了更可靠地映射这种事情,我们发现与@MapsId合作更成功。在那里,模块需要对 MainEntity 的引用,并将在其上使用 @MapsId 来派生其 id。