2

我对在 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 会为我处理这个问题。

更新

在进行任何更改之前,我已经调整了我的代码以首先从数据库中获取实体,但它仍然没有删除我的子电子邮件实体。我想知道这是否是 apache derby 问题。(这是正确的方法,因为我将我的实体从我的 JSF 托管 bean 传递到我的 EJB 中,所以我需要先从数据库中获取同步。)

@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);
}
4

3 回答 3

1

由于您已经定义了 cascade type = CascadeType.ALL,因此 JPA 应该负责删除。Explicit Delete声明不是必需的。

这两个语句不是必需的:

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

相反,您可能只想在其中找到匹配项emailReceiverconfig.getEmailReceivers()删除匹配EmailReceivers项。无需Email从数据库加载实体。

编辑:要删除孤立对象,您可能需要包含CascadeType.DELETE_ORPHAN级联属性以及CascadeType.ALL.

于 2012-10-31T02:52:47.253 回答
1

这与为什么合并不是在一对多关系上级联中的问题相同

基本上,JPA 只能级联您集合中的实体。因此,从集合中删除的子对象的更改永远不会放入上下文中,因此不能推送到数据库中。在这种情况下,oneToMany 由多音返回指针控制,因此除非子元素也被合并,否则即使集合更改也不会显示。一旦从树中修剪出一个子节点,就需要单独管理和合并它,以便获取对它的更改。

于 2012-10-31T12:45:12.390 回答
1

使用 JPA 2.0,您可以在父实体中使用选项 orphanRemoval=true

例子:

@Entity
public class Parent {
    ...

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

}
于 2015-12-09T22:51:40.423 回答