我正在处理需要级联创建和通过大型JPA注释实体合并的WebSphere 8.5.5(OpenJPA 2.2.3)中的项目模型。在通过调用Grand-Parent上的EntityManager.merge()或者在事务提交时触发flush来合并grand-children时,我们遇到了一个非常具体的问题。下面是详细信息:插入JPA实体与复合EmbeddedId(包含另一个EmbeddedId的EmbeddedId)的顺序
实体映射的相关部分:
- EntityA具有一对多到EntityB
- EntityB具有一对多到EntityC
- EntityC具有一对多到EntityD
全部都有双向映射。实体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语句。为了让事情更加混乱,INSERTS的顺序在重复执行单元测试时是不一致的。它未能通过尝试实体C.
之前插入实体d的问题:
如何,我们纠正JPA注解,在合并执行正确的插入顺序(和更新/删除)?
编辑1: 插入/删除顺序至关重要,因为数据库强制外键关系与约束。
在这里看到我的答案,这可能是有用的:http://stackoverflow.com/questions/39024310/openjpa-nested-onetomany-relationships-merge-issue/39025865#39025865 –