删除OneToMany关系中的实体

时间:2011-10-30 15:33:12

标签: java hibernate jpa

我无法理解从OneToMany关系中删除实体所需的最小努力。我发现很多例子只是将实体添加到这些集合中(并且可以正常工作),但是删除实体要难得多。

我有以下课程:

@Entity
public class Product {
    ... 
    OneToMany(mappedBy="product", orphanRemoval=true,
              cascade={CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},fetch=FetchType.EAGER)
    Set<Expert> experts = new HashSet<Expert>();
    ...
}

@Entity
public class Expert {
    ...
    @ManyToOne(optional=false)
    Product product;

    @ManyToOne(optional=false)
    Person person;

    ...
}

(人与产品类似)

我充满了产品和专家。我想从产品列表中删除专家,以便完全删除专家实体。我希望以下代码就足够了:

Product aProduct = findAProduct(...);
Expert anExpert aProduct.getExperts.get(...); // Just get the first expert that I want removed
EntityManager em = entityManager();

  em.getTransaction().begin();
  aProduct.getExperts().remove(anExpert);
  em.merge(aProduct);
  em.getTransaction().commit();

或:

  em.getTransaction().begin();
  em.remove(anExpert);
  em.getTransaction().commit();

这太简单了吗? JPA做了什么,我自己要做什么?我之前只是使用查询解决了它,但我希望JPA能为我做到这一点。

3 个答案:

答案 0 :(得分:1)

尝试:

em.getTransaction().begin();
aProduct = em.merge(aProduct);
aProduct.getExperts().remove(anExpert);    
em.getTransaction().commit();

问题在于合并操作,而不是删除。

答案 1 :(得分:1)

根据我过去的经验,在Hibernate中删除亲子双向关系中的孩子可能会非常棘手。

我通常做的是使用单向映射,即产品不包含专家组。但是你可以实现一个getter来让所有专家使用Hibernate调用。优点是:

  1. 更容易制作地图
  2. 更容易编码
  3. 可管理的behviour
  4. 您可以随时返回并在稍后阶段实施缓存或急切提取。而且大多数时候它们都是不必要的预成熟优化。

答案 2 :(得分:1)

让它运作的方法是执行以下操作:

EntityManager em = entityManager();
// Retrieve the expert in the new EntityManager context 
Expert expertToDelete = em.find(Expert.class, anExpert.id);

em.getTransaction().begin();
expertToDelete.getProduct().getExperts().remove(expertToDelete);
expertToDelete.getPerson().getExperts().remove(expertToDelete);
em.remove(expertToDelete);
em.getTransaction().commit();

很可能不是通过find检索专家,而是在anExpert上使用merge(),但上面似乎有用。