2013-07-07 179 views
0

我需要幫助來了解ORM的工作原理。這是非常常見的情況。我有兩個主表Organization和RelatedParty,它們必須在許多關係中。但是還有一個relation_type屬性,用於定義組織和關聯方之間存在哪種關係。使用jpa更新多個實體2

relational database entity model

這裏是我的實體類: 組織:

@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

回答

0

你似乎使這些大量複雜得多,他們需要。

你爲什麼不移除已經被移除的Organdrelatedparty,而不是刪除它們,然後重新生成其中的一些?轉生對象,特別是在同一交易中通常是一個糟糕的主意。

正在發生的錯誤是根據您包含的代碼在merge()上只是在updateOrgAndRelatedShares()中調用合併,所以我沒有看到這個對象在此時如何被移除?或者你的代碼與你顯示的不同,請包含異常堆棧。

您的updateOrganization()方法不好,它會更新對象Id,您永遠不應該這樣做。它也無緣無故地調用合併,它已經改變了對象。

此外,我通常會推薦使用IdClass而不是EmbeddedId,並建議使用TABLE或SEQUENCE id代替代替IDENTITY。