我正在處理需要級聯創建和通過大型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 –