2012-10-31 84 views
2

我對管理JPA中的關係有點困惑。 基本上我有兩個具有一對多關係的實體顯式刪除JPA關係

一個配置可以有一個或多個與之關聯的電子郵件列表。

@Entity 
public class Config { 
    @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    private List<Email> emailReceivers; 
} 
@Entity 
public class Email { 
    @ManyToOne 
    private Config owner; 
} 

在EJB和更新/合併操作中,其中我將編輯與配置相關聯的電子郵件列表, 我認爲我不需要顯式調用我的電子郵件實體刪除操作,我只想通過刪除配置電子郵件列表中的電子郵件來管理關係。

@Stateless 
public class ConfigFacadeImpl implements ConfigFacade{ 
    @EJB 
    private ConfigDao configDao; 
    @EJB 
    private EmailDao emailDao; 

    @Override 
    public void update(Config Config, List<Email> emailsForDelete) { 
     if(emailsForDelete!=null && emailsForDelete.size() > 0){ 
      for(Email emailTemp: emailsForDelete){ 
       Email email = emailDao.find(emailTemp.getId()); 
       emailDao.delete(email); // Do I need to explicitly call the remove?? 
       config.getEmailReceivers().remove(email); 
      } 
     } 
     configDao.update(config); 
    } 
} 

如果我不執行刪除操作,只能從列表中刪除它,它不會刪除我的表格行。

UI和數據庫現在不同步,因爲UI不會顯示我已刪除的電子郵件,但當您檢查數據庫時,行仍然存在。

是否需要?我認爲JPA會爲我處理這個問題,如果我只是在我的實體中刪除它。

UPDATE

我已經調整了我的代碼,第一個做出任何更改,但它仍然是不刪除我的孩子電子郵件實體之前,從數據庫中獲取的實體。我不知道這是一個Apache的德比問題。 (這是正確的,因爲我通過我的實體從我的JSF託管bean到我的EJB,所以我需要首先從DB獲得同步的正確方法。)

@Override 
public void update(Config config, List<Email> emailsForDelete) { 
    Config configTemp = configDao.find(config.getId()); 
    if(emailsForDelete!=null && emailsForDelete.size() > 0){ 
     for(Email emailTemp: emailsForDelete){ 
      configTemp.getEmailReceivers().remove(emailTemp); 
     } 
    } 
    configDao.update(config); 
} 

回答

1

既然你已經定義級聯型= CascadeType.ALL ,JPA應該照顧刪除。 Explicit Delete聲明是不需要。不需要

這兩句話:

 Email email = emailDao.find(emailTemp.getId()); 
    emailDao.delete(email); // Do I need to explicitly call the remove?? 

相反,你可能只想找到config.getEmailReceivers()匹配emailReceiver並取出匹配EmailReceivers,你在做什麼。不需要從數據庫加載Email實體。

編輯:要刪除孤立對象,您可能需要包含CascadeType.DELETE_ORPHAN級聯屬性以及CascadeType.ALL

+0

你是什麼意思呢?我實際上並沒有刪除我的所有emailReceivers ..只有一些從我的JSF UI刪除的項目。如果我註釋掉emailDao.delete,它不會刪除我的電子郵件表中的條目 –

+0

@MarkEstrada NO。 'CascadeType.ALL'相當於cascade = {PERSIST,MERGE,REMOVE,REFRESH,DETACH}。在保存時,它只會刪除您從集合中刪除的記錄,例如如果你的配置爲5個電子郵件接收器,並刪除其中的2個,然後保存配置;它會刪除只有2個不是全部5. –

+0

這是我的理解,因爲我只是閱讀和在線教程...我只是不知道爲什麼我的代碼仍然不刪除我的電子郵件列表,如果我刪除代碼行明確刪除它。 –

1

這是同樣的問題,因爲在Why merging is not cascaded on a one to many relationship

基本上,JPA只能在您的收藏中的實體級聯。因此,從集合中刪除的子對象的更改永遠不會放到上下文中,因此不能推送到數據庫。在這種情況下,oneToMany由manytones後面的指針控制,所以即使集合更改也不會顯示,除非該子項也被合併。一旦孩子從樹上剪下來,需要對它進行管理和合並,以便對其進行修改以便拾取。

1

使用JPA 2。0,你可以使用

實例的選項母公司orphanRemoval =真:

@Entity 
public class Parent { 
    ... 

    @OneToMany(mappedBy="parentId",cascade=CascadeType.ALL, orphanRemoval=true) 
    private List<Child> childList; 
    ... 

}