级联更新/删除JPA 2.0

时间:2014-05-13 13:50:50

标签: java-ee jpa cascade

我有与这3个实体映射的n-n关系:

@Entity
public class ApplicatifDo {
   .....
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "applicatifDo", fetch = FetchType.EAGER, orphanRemoval = true)
   private Set<ApplicatifTerminalDo> applicatifTerminalSet;
   .....
}

@Entity
public class ApplicatifTerminalDo {
   ......
   @ManyToOne
   @JoinColumn(name = "idApplicatif", nullable = false)
   private ApplicatifDo applicatifDo;
   @ManyToOne
   @JoinColumn(name = "idTerminal", nullable = false)
   private TerminalDo terminalDo;

   @Column
   private String remarques;
   ......
}

@Entity
public class TerminalDo {
   ......
   @OneToMany(cascade = CascadeType.ALL, mappedBy = "terminalDo", fetch = FetchType.EAGER, orphanRemoval = true)
   private Set<ApplicatifTerminalDo> applicatifTerminalSet;
   ......
}

我尝试进行测试,其中我有一个ApplicatifDo持久化,其中包含许多ApplicatifTerminalDo,并且我更改了这些的一些值,删除其他值,在此集合中添加新的:

modifyRemarques(firstElement(applicatifDo.getApplicatifTerminalSet()));
applicatifDo.getApplicatifTerminalSet.add(anotherApplicatifTerminal);
applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal);

然后当我合并时,在我的数据库中,在我的连接表ApplicatifTerminal中,我看到出现了“Remarques”的修改,以及出现的新ApplicatifTerminal实体,但删除没有工作,应该删除的实体仍然存在于我的连接表中(我使用orphanRemoval)。

当我测试时,我在控制台中没有出现任何错误,但是删除实体仍然不应该在DB中。

PS:我在1-n关系上使用了相同的方法,并且父实体中包含的实体集上的所有类型修改的级联都运行良好(包括删除)。

更新:

我试图从ChrisDo中删除OnceApplicatifTerminal,但仍然无法正常工作。这是代码:

            Iterator<ApplicatifTerminalDo> iterator = applicatifDo
                .getApplicatifTerminalSet().iterator();
            boolean first = true;
            while (iterator.hasNext()) {
                ApplicatifTerminalDo element = iterator.next();
                if (!first) {
                    element.setRemarques("remarques updated");
                } else {
                    iterator.remove();
                    element.getTerminalDo().setApplicatifTerminalSet(
                            applicatifDo.getApplicatifTerminalSet());
                    first = false;
                }
            }

在这里,我尝试从列表中删除第一个ApplicatifTerminalDo,并为其他人更新列值。当我合并时,值会被更改,但删除不起作用,即使我让TerminalDo删除了更新的ApplicatfTerminal Set。

有可能实现我想做的事吗? 从个人联接表中更新/删除行的最佳做法是什么?

请帮助,我不明白为什么。

1 个答案:

答案 0 :(得分:0)

您期望孤儿删除能够启动,因为您已取消引用OnceApplicatifTerminal,并希望OnceApplicatifTerminal。

Orphan删除有一些缺点,当它在其他ORM中称为私有所有权时会暗示:实体实际上应该只是私有,这不是这里的情况。当您调用applicatifDo.getApplicatifTerminalSet.remove(onceApplicatifTerminal);时遇到问题,因为存在一个也引用此onceApplicatifTerminal实例的TerminalDo实例。 JPA允许使用缓存,因此除非在您的实体中清除此TerminalDo-&gt; onceApplicatifTerminal,否则会留下对onceApplicatifTerminal实体的引用,并且由于您的级联Persist / Merge设置,这会导致它复活。只需删除TerminalDo-&gt; ApplicatifTerminalDo上的级联设置,就好像未删除引用一样,缓存仍将保留引用此不存在的实体。

应谨慎使用孤立删除,并且仅适用于其他实体未引用引用实体的关系,或者需要注意事先清理这些引用。