本文介绍了一对多关系JPA / Hibernate删除链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我有双向关系设置,如下所示: class Child { @ManyToOne @JoinTable (name =CHILDREN_WITH_PARENT, joinColumns = {@JoinColumn(name =CHILD_ID)}, inverseJoinColumns = {@JoinColumn(name =PARENT_ID)} )私人父母; } 类父母{ @OneToMany(mappedBy =parent,cascade = CascadeType.ALL) Set< Child> childrens = new HashSet< Child>(); public void persistOrMerge(){ EntityManager em = entityManager(); em.getTransaction()。begin(); 尝试{ if(em.contains(this)) return; if(id == null || id == 0){ this.setCreatedDate(new Date()); em.persist(this); } else { Parent prev = em.find(Parent.class,this.id); if(prev == null){ em.persist(this); } else { this.setCreatedDate(new Date()); em.merge(this); } } em.flush(); em.getTransaction()。commit(); } finally { em.close(); code $ b Set< ChildProxy> children = new HashSet< ChildProxy>(); if(childIsNew) child = request.create(Children.class) else child = request.edit(oldChild) children.add(child); //如果子项被删除,它们不包含在set 中//我们将发送回服务器 parent.setChildren(children) parent.persistOrMerge(); 此代码仅适用于添加新的子项。即使父母课程收到一个空的儿童套装,从父母中移除孩子也不起作用。 您可以告诉我在哪里丢失了什么? 感谢!解决方案我会先说这是一个非常糟糕的主意,实体是使用实体的实体直接经理。 EntityManager.merge()方法返回实际的合并实例,这意味着在您的代码中,当您发出 em.merge(this) 您没有保证合并的实例不再与this相对应,从这一点开始,您可能会看到各种逻辑问题。 如果你不认为这是这样的一个重大的问题,你应该通过打开关系的OneToMany一边的孤儿删除来解决你的问题,前提是这些孩子没有被用在其他关系中的任何其他地方。 @OneToMany(mappedBy =parent,cascade = CascadeType.ALL,orphanRemoval = true) Set< Child> childrens = new HashSet< Child>(); JPA 2.0规范声明: 指定为OneToOne或OneToMany的关联支持使用orphanRemoval 选项。当orphanRemoval生效时,以下行为适用: 如果一个实体是的目标, 关系(通过将关系设置为null或从关系集合中除去实体),删除操作将应用于实体孤儿。删除操作是在冲洗操作时应用的。 orphanRemoval 功能适用于由其父实体私有拥有的实体。便携式应用程序必须否则不能取决于特定的删除顺序,并且不得重新分配实体,该实体已被孤立为另一种关系或试图坚持它。如果被孤立的实体是已分离的,新的或被删除的实体,则 orphanRemoval的语义不适用。 如果删除操作应用于a托管来源实体,则删除操作将按照与第3.2.3节的规则(和)级联至关系目标因此没有必要为关系指定 cascade = REMOVE)[20]。 I have bidirectional relationship setup as follows:class Child{ @ManyToOne @JoinTable(name = "CHILDREN_WITH_PARENT", joinColumns = {@JoinColumn(name = "CHILD_ID")}, inverseJoinColumns = {@JoinColumn(name = "PARENT_ID")} ) private Parent parent;}class Parent{ @OneToMany(mappedBy="parent", cascade=CascadeType.ALL) Set<Child> childrens = new HashSet<Child>(); public void persistOrMerge() { EntityManager em = entityManager(); em.getTransaction().begin(); try { if (em.contains(this)) return; if (id == null || id == 0) { this.setCreatedDate(new Date()); em.persist(this); } else { Parent prev = em.find(Parent.class, this.id); if (prev == null) { em.persist(this); } else{ this.setCreatedDate(new Date()); em.merge(this); } } em.flush(); em.getTransaction().commit(); } finally { em.close(); } }}On my client side I have following code (GWT + EntityProxy)Set<ChildProxy> children = new HashSet<ChildProxy>();if(childIsNew) child = request.create(Children.class)else child = request.edit(oldChild)children.add(child);//If children are deleted, they are not contained in the set//we are sending back to serverparent.setChildren(children)parent.persistOrMerge();This code only works for adding new children. Removing of children from parent does not work even if parent class receives an empty children set. The linkages in JOIN table are not removed.Can you please tell where I am missing something?Thanks! 解决方案 I will start by saying that is a really bad idea that the entity is the one using the entity manager directly.The EntityManager.merge() method returns the actual merged instance, this implies that in your code, when you issueem.merge(this)You have no guarantee whatsoever that the merged instance corresponds to "this" anymore, and from that point on you may see all kinds of logical problems.If you do not think this is such a big deal, your problem should be solved by turning on orphan removal on the OneToMany side of the relationship, provided that the children are not being used anywhere else in other relationships. Otherwise you will have to do the merging manually.@OneToMany(mappedBy="parent", cascade=CascadeType.ALL, orphanRemoval=true)Set<Child> childrens = new HashSet<Child>();The JPA 2.0 specification states thatAssociations that are specified as OneToOne or OneToMany support use of the orphanRemovaloption. The following behaviors apply when orphanRemoval is in effect:If an entity that is the target ofthe relationship is removed from therelationship (by setting therelationship to null or removing theentity from the relationshipcollection), the remove operationwill be applied to the entity beingorphaned. The remove operation isapplied at the time of the flushoperation. The orphanRemovalfunctionality is intended forentities that are privately "owned"by their parent entity. Portableapplications must otherwise notdepend upon a specific order ofremoval, and must not reassign anentity that has been orphaned toanother relationship or otherwiseattempt to persist it. If the entitybeing orphaned is a detached, new,orremoved entity, the semantics oforphanRemoval do not apply.If the remove operation is applied toa managed source entity, the removeoperation will be cascaded to therelationship target in accordancewith the rules of section 3.2.3, (andhence it is not necessary to specifycascade=REMOVE for therelationship)[20]. 这篇关于一对多关系JPA / Hibernate删除链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-23 08:43