【发布时间】:2017-04-30 06:35:10
【问题描述】:
我正在开发一个 WebSphere 8.5.5 (OpenJPA 2.2.3) 项目,该项目需要通过大型 JPA 注释实体模型进行级联创建和合并。通过在祖父母上调用 EntityManager.merge() 或在事务提交时触发刷新来合并孙子时,我们遇到了一个非常具体的问题。以下是详细信息:
实体映射的相关部分:
- EntityA 与 EntityB 有 oneToMany
- EntityB 与 EntityC 之间存在 oneToMany
- EntityC 与 EntityD 之间存在 oneToMany
都有双向映射。实体 A 和 B 具有单列主键。实体 C 有一个复合主键,其中包含实体 B 的主键的外键。实体 D 有一个复合键,其中包含实体 C 的复合键。请参阅下面的映射。
@Entity
@Table(name="TableA")
public class EntityA extends BaseEntity {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_A_ID_GEN")
@SequenceGenerator(name="TABLE_A_ID_GEN", sequenceName="TABLE_A_ID", allocationSize=1)
@Column(name="TABLE_A_ID")
private Integer id;
@OneToMany(fetch=FetchType.LAZY, mappedBy="entityA", cascade=CascadeType.ALL)
private List<EntityB> entityBList;
...
}
@Entity
@Table(name="TableB")
public class EntityB extends BaseEntity {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_B_ID_GEN")
@SequenceGenerator(name="TABLE_B_ID_GEN", sequenceName="TABLE_B_ID", allocationSize=1)
@Column(name="TABLE_B_ID")
private Integer id;
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinColumn(name="TABLE_A_ID")
private EntityA entityA;
@OneToMany(fetch=FetchType.LAZY, mappedBy="entityB", cascade=CascadeType.ALL)
private List<EntityC> entityCList;
...
}
@Entity
@Table(name="TableC")
public class EntityC extends BaseEntity {
@EmbeddedId
private EntityC_PK id = new EntityC_PK();
@MapsId("entityB_Id")
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
@JoinColumn(name="TABLE_B_ID")
private EntityB entityB;
@OneToMany(fetch=FetchType.LAZY, mappedBy="entityC", cascade=CascadeType.ALL)
private List<EntityD> entityDList;
...
}
@Embeddable
public class EntityC_PK implements BaseComponent {
@Column(name="TABLE_B_ID", nullable = false, updatable = false)
private Integer entityB_Id;
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_C_ID_GEN")
@SequenceGenerator(name="TABLE_C_ID_GEN", sequenceName="TABLE_C_ID", allocationSize=1)
@Column(name="TABLE_C_ID")
private Integer entityC_Id;
...
}
@Entity
@Table(name="TABLE_D")
public class EntityD extends BaseEntity {
@EmbeddedId
private EntityD_PK id = new EntityD_PK();
@MapsId("entityC_Id")
@JoinColumns({
@JoinColumn(name = "TABLE_B_ID"),
@JoinColumn(name = "TABLE_C_ID")})
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private EntityC entityC;
...
}
@Embeddable
public class EntityD_PK implements BaseComponent {
@Embedded
private EntityC_PK entityC_Id;
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="TABLE_D_ID_GEN")
@SequenceGenerator(name="TABLE_D_ID_GEN", sequenceName="TABLE_D_ID", allocationSize=1)
@Column(name="TABLE_D_ID")
private Integer entity_id;
...
}
什么有效:
您可以在实体 A 上调用 EntityManager.persist()(附加所有子级),模型将正确级联持久化。
什么不起作用:
如果您实例化实体 A 并调用 EntityManager.persist(entityA) 并在 EntityManager.merge(entityA) 时添加子代、孙代等(或在提交事务时允许隐式合并),它将失败以正确的顺序执行 INSERT 语句。为了使事情更加混乱,插入的顺序在单元测试的重复执行中是不一致的。尝试在实体 C 之前插入实体 D 失败。
问题:
我们如何更正 JPA 注释以在合并时强制执行正确的插入顺序(和更新/删除)?
编辑 1: 插入/删除顺序很关键,因为数据库强制执行带有约束的外键关系。
【问题讨论】:
-
在这里查看我可能有用的答案:stackoverflow.com/questions/39024310/…
标签: java jpa jakarta-ee openjpa websphere-8