2011-04-12 65 views
6

如何刪除OneToMany關係中的實體。JPA2.0:刪除OneToMany RelationShip中的實體

@Entity 
@NamedQueries({ 
    @NamedQuery(name="User.findByUserNamePassword", 
    query="select c from User c where c.userName = :userName AND c.password = :password") 
}) 
@Table(name="\"USER\"") 
public class User implements Serializable { 
    @OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemove=true) 
    private List<Profession> professions; 

    public List<Profession> getProfessions() { 
     return professions; 
    } 

    public void setProfessions(List<Profession> professions) { 
     this.professions = professions; 
    } 

    public void addProfession(Profession profession){ 
     if(this.professions == null){ 
      this.professions = new ArrayList<Profession>(); 
     } 
     this.professions.add(profession); 
     profession.setUser(this); 
    } 

    public void removeProfession(Profession profession){ 
     if(this.professions != null){ 
      professions.remove(profession); 
      profession.setUser(null); 
     } 
    } 
} 

行業內實體

@Entity 
public class Profession implements Serializable { 
    @ManyToOne 
    @JoinColumn(name="UserId", nullable=false) 
    private User user; 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

然後我EJB裏面我有這個

@Stateless 
@LocalBean 
@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public class ScholarEJB{ 

    /** 
    * Add a profession to a target user 
    * @param user 
    * @param profession 
    */ 
    public void addProfession(User user, Profession profession){ 
     //Put the user in a managed state. It is important to do this before 
     //adding a new profession onto user 
     user = find(User.class, user.getId()); 
     user.addProfession(profession); 
     this.create(user); //This is persist action 
    } 

    public void removeProfession(User user, Profession profession){ 
     //Put the user in a managed state. It is important to do this before 
     //adding a new profession onto user 
     user = find(User.class, user.getId()); 
     user.remove(user); 
     this.update(user); //merge action 
     //this.create(user) //also try this as well, but it does not work 
    } 
} 

現在addProfession做工精美,但removeProfession不起作用。不知道爲什麼?請幫助。我需要驅逐高速緩存嗎?

+0

在你的一對多的關係,正確的註釋是orphanRemoval =真的,不是orphanRemove =真 – greuze 2011-08-10 08:25:48

回答

1

你可以嘗試清除在行業用戶領域:

public void removeProfession(Profession profession){ 
     if(this.professions != null){ 
      professions.remove(profession); 
      profession.setUser(null); // disassociate profession from user 
     } 
    } 

爲了安全起見,我還要檢查在行業的當前用戶通過等於this,以防萬一有人經過的職業屬於另一個用戶。

+0

嘗試爲好,不能正常工作。在我刪除之後,在我堅持/合併之前,我打印出專業列表,列表恢復正確。但是當我堅持/合併,這並不反映在我的數據庫 – 2011-04-12 22:22:06

9

如果職業只是這種關係的一部分,那麼你可以保證,當一個職業從用戶的設置中刪除時,它也將通過在關係的OneToMany側打開orphanRemoval從數據庫中刪除。

@OneToMany(mappedBy="user", cascade=CascadeType.ALL, orphanRemoval=true) 
private List<Profession> professions; 

這是JPA 2.0規範狀態

的JPA 2.0規範規定什麼被指定爲 OneToOne或一對多支持使用 的orphanRemoval選項

協會。當 orphanRemoval是生效的 應用以下行爲:

如果是 關係的目標的實體從 關係移除(通過從關係 設置 關係爲空或去除 實體收集),刪除操作將 應用於實體 成爲孤兒。刪除操作是在沖洗 操作時應用的 。孤立刪除 功能適用於實體 ,這些實體由其 父實體私有「擁有」。便攜式應用程序 必須不依賴 刪除的特定順序,並且必須 不會重新分配已被其他關係孤立的實體或 否則會嘗試保留它。如果 孤立的實體是 分離的,新的或移除的實體,則應用odphanRemoval的語義 。

如果刪除操作被施加到一個 管理的源實體,所述刪除 操作將按照第3.2節的 規則級聯到 關係目標。3,(因此 沒有必要指定 cascade = REMOVE爲 關係)[20]。

+1

可悲的是我嘗試它,但仍然無法正常工作。但我找出了什麼工作。我必須清除二級緩存才能工作。專業= em.merge(職業); em.remove(職業); em.getEntityManagerFactory()。getCache()。evictAll();',這項工作,但我不確定這是否是最好的方法 – 2011-04-12 23:29:05

+0

你的文章可以發佈你的更新方法嗎?它表示它進行了合併,這在目前的代碼中並不清楚或明顯。 – 2011-04-12 23:48:45

+0

我轉發我的代碼。請檢查出 – 2011-04-13 00:04:23

1

這是解決我原來的問題,但是,我不知道這是不是最好的

我EJB豆

@PersistenceContext(unitName="Bridgeye2-ejbPU") 
private EntityManager em; 

public <T> T create(T t) { 
    em.persist(t); 
    return t; 
} 

public <T> T find(Class<T> type, Object id) { 
    return em.find(type, id); 
} 

public <T> void delete(T t) { 
    t = em.merge(t); 
    em.remove(t); 
} 

public <T> void removeAndClearCaches(T t){ 
    this.delete(t); 
    clearCaches(); 
} 

public <T> T update(T t) { 
    return em.merge(t);  

現在在我的Managed Bean的,我這樣做

/** 
* Add a new profession 
*/ 
public void addNewProfession(){ 
    Profession profession = new Profession();   
    newProfessions.add(profession);   
} 

/** 
* Remove the profession 
* @param profession 
*/ 
public void removeProfession(Profession profession){ 
    //This will remove the `profession` of the list 
    //at the presentation layer 
    this.myProfessions.remove(profession); 
    //This will remove the `profession` of the list 
    //at the persistence layer 
    scholarEJB.removeAndClearCaches(profession); 
} 
4

我的猜測是你的用戶與專業有一對多的關係,而你的用戶對象有專業。當你刪除職業時,用戶仍然有參考。因爲映射是級聯的,所以它繼續存在職業。

您需要確保在刪除用戶職業之前將其從職業中​​刪除。

如果您使用的是EclipseLink,有一個屬性可能也有幫助,但修復代碼以正確維護模型是最佳解決方案。你也可以刪除cascade persist。

「eclipselink.persistence-context.persist上提交」= 「假」

,或者 「eclipselink.persistence-context.commit - 沒有 - 堅持規則」= 「真」

0

我剛剛在OneToMany關係中添加了orphanRemoval = true,我解決了它。

SolicitudRetorno

@OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true) 
@LazyCollection(LazyCollectionOption.FALSE) 
@NotAudited 
private List<RetornoMenor> hijosRetorno; 

RetornoMenor

@OneToMany(mappedBy = "solicitud", cascade = CascadeType.ALL, orphanRemoval = true) 
@LazyCollection(LazyCollectionOption.FALSE) 
@NotAudited 
private List<RetornoMenor> hijosRetorno;