我需要幫助來了解ORM的工作原理。這是非常常見的情況。我有兩個主表Organization和RelatedParty,它們必須在許多關係中。但是還有一個relation_type屬性,用於定義組織和關聯方之間存在哪種關係。使用jpa更新多個實體2
這裏是我的實體類: 組織:
@Entity
@Table(name = "organization", catalog = "...", schema = "")
@XmlRootElement
public class Organization implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "organization_id", nullable = false)
private Integer organizationId;
@Column(name = "organization_name", nullable = false)
private String organizationName;
@OneToMany(cascade = {CascadeType.ALL}, mappedBy = "organization")
private List<Organdrelatedparty> organdrelatedpartyList;
...
//getter setter methods
Organdrelatedparty:它採用複合主鍵OrgandrelatedpartyPK
@Entity
@Table(name = "organdrelatedparty", catalog = "...", schema = "")
@XmlRootElement
public class Organdrelatedparty implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
protected OrgandrelatedpartyPK organdrelatedpartyPK;
@JoinColumn(name = "relatedParty_id", referencedColumnName = "relatedParty_id", nullable = false, insertable = false, updatable = false)
@ManyToOne(optional = false, cascade= {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
private Relatedparty relatedparty;
@JoinColumn(name = "orgRelation_id", referencedColumnName = "orgRelation_id", nullable = false)
@ManyToOne(optional = false)
private ParOrgrelationtype orgRelationid;
@JoinColumn(name = "organization_id", referencedColumnName = "organization_id", nullable = false, insertable = false, updatable = false)
@ManyToOne(optional = false)
private Organization organization;
...
//getter setter methods
OrgandrelatedpartyPK
@Embeddable
public class OrgandrelatedpartyPK implements Serializable {
@Basic(optional = false)
@NotNull
@Column(name = "relatedParty_id", nullable = false)
private int relatedPartyid;
@Basic(optional = false)
@NotNull
@Column(name = "organization_id", nullable = false)
private int organizationId;
...
//getter setter methods
RelatedParty:它與organdRelatedParty類處於單向oneToMany關係。換言之,relatedParty實體對另一側的organdRelatedParty實體不瞭解。
@Entity
@Table(name = "relatedparty", catalog = "...", schema = "")
@XmlRootElement
public class Relatedparty implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "relatedParty_id", nullable = false)
private Integer relatedPartyid;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 100)
@Column(name = "firstName", nullable = false, length = 100)
private String firstName;
@Size(max = 100)
@Column(name = "lastName", length = 100)
private String lastName;
@Basic(optional = false)
@NotNull
@Column(name = "isForeign", nullable = false)
private boolean isForeign;
...
//getter setter methods
對於插入,如果我堅持新的組織實體,它級聯堅持活動,新OrgandrelatedParty也級聯堅持活動,新RelatedParty。所以所有相關的實體都被保留下來並且工作正常。
對於更新,用戶有望改變現有的組織和relatedParty實體,並添加新的relatedParty來組織。因此,我們首先刪除所有OrgandrelatedParties,然後再添加新的relatedParties並編輯relatedParties。
這是我們的方法來處理更新:我們通過新的組織以及所有新老relatedParties作爲一個列表方法: 冷杉我們刪除所有舊OrgAndRelatedParties那麼我們在列表作爲新OrgandrelatedParties再次創造一切relatedParties。這是更新組織的主要方法。
public void updateOrganization(Organization newOrganization, List<Relatedparty> newShareList) throws ControlException {
try{
tx.begin();
this.updateOrgAndRelatedShares(newOrganization, newShareList);
customerController.updateOrganization(newOrganization);
tx.commit();
}catch(ControlException ex){
...
customerController的updateOrganization方法,通過實體管理器的查找方法不先找到老單位,然後拷貝新組織舊的所有屬性然後合併舊的組織和沖洗:
public void updateOrganization(Organization newOrganization)
{
Organization preOrganization = em.find(Organization.class, newOrganization.getOrganizationId);
preOrganization.setOrganizationId(newOrganization.getOrganizationId);
preOrganization.setOrganizationName(newOrganization.getOrganizationName);
em.merge(preOrganization);
em.flush();
}
這裏有其他的方法:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
private void updateOrgAndRelatedShares(Organization org, List<Relatedparty> shareList) throws ControlException
{
for(Iterator<Organdrelatedparty> it = org.getOrgandrelatedpartyList().iterator(); it.hasNext();)
{
Organdrelatedparty op = it.next();
it.remove();
op.setOrganization(null);
op.setRelatedparty(null);
deleteOrgRelated(op);
}
org.getOrgandrelatedpartyList().clear();
for(Relatedparty relatedParty: shareList){
int parOrgRelationTypeId = relatedParty.getIsPerson() ? 1:2;
createOrgAndRelatedParty(org, relatedParty, parOrgRelationTypeId);
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void deleteOrgRelated(Organdrelatedparty org) throws ControlException{
try{
org = em.find(Organdrelatedparty.class, org.getOrgandrelatedpartyPK());
em.remove(org);
em.flush();
}
catch(Exception ex){
Logger.getLogger(RelatedpartyController.class.getName()).log(Level.SEVERE, null, ex);
throw new ControlException("Couln't delete org relation", ex);
}
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
private void createOrgAndRelatedParty(Organization org, Relatedparty relatedParty, int parOrgRelationTypeId) throws ControlException{
if(findRelatedPartyByRegNum(relatedParty.getRegisterNumber()) == null || relatedParty.getRelatedPartyid() == null){
createRelated(relatedParty);
}else{
relatedParty = updateRelatedParty(relatedParty);
}
Organdrelatedparty preOrp = new Organdrelatedparty(relatedParty.getRelatedPartyid(),
preOrp.setOrganization(org);
preOrp.setRelatedparty(relatedParty);
preOrp.setOrgRelationid(prepareOrgandRelatedPartyType(parOrgRelationTypeId));
org.getOrgandrelatedpartyList().add(preOrp);
}
而我的問題是,當我合併組織實體與新列表organdrelatedpartyList 它拋出像這樣的異常:
SEVERE: java.lang.IllegalArgumentException: Cannot merge an entity that has been removed: mn.bsoft.crasmonclient.model.Organdrelatedparty[ organdrelatedpartyPK=mn.bsoft.crasmonclient.model.OrgandrelatedpartyPK[ relatedPartyid=71, organizationId=19 ] ]
我發現eclipseLink會先保留操作然後刪除操作。所以我認爲它試圖插入organdrelatedparty實體,它具有與以前沒有從數據庫中刪除過的實體相同的合成id。每次我移除舊有關聯的對象時,我都會刷新。但它沒有幫助。解決辦法是什麼?任何想法的傢伙。
我正在使用jpa 2.0;如的EclipseLink提供商和GlassFish 3.1.2