删除OneToMany关系中的实体

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

我有以下课程:

@Entity public class Product { ... OneToMany(mappedBy="product", orphanRemoval=true, cascade={CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH},fetch=FetchType.EAGER) Set experts = new HashSet(); ... } @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能为我做到这一点。

尝试:

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

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

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

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

  1. 更容易映射
  2. 更容易编码
  3. 可管理的行为

您可以随时返回并在稍后阶段实施缓存或急切提取。 而且大多数时候它们都是不必要的预成熟优化。

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

 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(),但上面似乎有效。