【问题标题】:JPA CascadeType.ALL does not delete orphansJPA CascadeType.ALL 不删除孤儿
【发布时间】:2010-09-23 07:09:02
【问题描述】:

我在使用具有以下映射的 JPA 删除孤立节点时遇到问题

@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;

我遇到了数据库中存在孤立角色的问题。

我可以使用注解 org.hibernate.annotations.Cascade Hibernate 特定标签,但显然我不想将我的解决方案绑定到 Hibernate 实现中。

编辑:似乎 JPA 2.0 将包含对此的支持。

【问题讨论】:

    标签: java hibernate orm jpa jpa-2.0


    【解决方案1】:

    如果您将它与 Hibernate 一起使用,则必须显式定义注释 CascadeType.DELETE_ORPHAN,它可以与 JPA CascadeType.ALL 一起使用。

    如果您不打算使用 Hibernate,则必须先显式删除子元素,然后再删除主记录以避免任何孤立记录。

    执行顺序

    1. 获取要删除的主行
    2. 获取子元素
    3. 删除所有子元素
    4. 删除主行
    5. 关闭会话

    使用 JPA 2.0,您现在可以使用选项 orphanRemoval = true

    @OneToMany(mappedBy="foo", orphanRemoval=true)
    

    【讨论】:

    • 感谢我最终选择了这条路线,我认为这对于 JPA 规范来说有点过分了。
    • JPA 2.0 标准现在将 deleteOrphan 作为@OneToMany 的属性如果您使用的是最新的休眠,您可以使用@OneToMany(..., deleteOrphan=true)
    • 更新子元素时的执行顺序是什么?孤儿记录会被删除吗?
    【解决方案2】:

    如果您使用的是 JPA 2.0,您现在可以使用 @xxxToMany 注释的 orphanRemoval=true 属性来删除孤儿。

    实际上,CascadeType.DELETE_ORPHAN 在 3.5.2-Final 中已被弃用。

    【讨论】:

    【解决方案3】:
    ╔═════════════╦═════════════════════╦═════════════════════╗
    ║   Action    ║  orphanRemoval=true ║   CascadeType.ALL   ║
    ╠═════════════╬═════════════════════╬═════════════════════╣
    ║   delete    ║     deletes parent  ║    deletes parent   ║
    ║   parent    ║     and orphans     ║    and orphans      ║
    ╠═════════════╬═════════════════════╬═════════════════════╣
    ║   change    ║                     ║                     ║
    ║  children   ║   deletes orphans   ║      nothing        ║
    ║    list     ║                     ║                     ║
    ╚═════════════╩═════════════════════╩═════════════════════╝
    

    【讨论】:

    • 如果我有cascade = CascadeType.ALL, orphanRemoval = false 并删除父级会怎样?即使我明确告知不要这样做,它会删除孩子吗?
    【解决方案4】:

    如果您将 JPA 与 EclipseLink 一起使用,则必须设置 @PrivateOwned 注释。

    文档:Eclipse Wiki - Using EclipseLink JPA Extensions - Chapter 1.4 How to Use the @PrivateOwned Annotation

    【讨论】:

      【解决方案5】:

      您可以使用@PrivateOwned 删除孤儿 例如

      @OneToMany(mappedBy = "masterData", cascade = {
              CascadeType.ALL })
      @PrivateOwned
      private List<Data> dataList;
      

      【讨论】:

      • 感谢@reshma 应该注意@PrivateOwned 是一个eclipselink JPA 扩展。
      【解决方案6】:

      我只是找到了这个解决方案,但在我的情况下它不起作用:

      @OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) 
      

      orphanRemoval = true 无效。

      【讨论】:

      • 我需要在更改生效之前进行清理和构建。
      • 哇,我一直在寻找一个小时,为什么在我的 ManyToOne 上添加 CascadeType.ALL 不是级联删除。清洁和建造,它的工作原理。谢谢@maralbjo。
      【解决方案7】:

      根据Java Persistence with Hibernate级联孤儿删除 不能用作 JPA 注释。

      JPA XML 也不支持它。

      【讨论】:

        【解决方案8】:

        我有同样的问题,我想知道为什么下面的这个条件没有删除孤儿。当我执行命名删除查询时,Hibernate(5.0.3.Final)中的菜肴列表没有被删除:

        @OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
        private List<Dish> dishes = new ArrayList<>();
        

        然后我记得我不能使用命名删除查询,而是使用 EntityManager。当我使用EntityManager.find(...) 方法获取实体然后EntityManager.remove(...) 删除它时,菜肴也被删除了。

        【讨论】:

          【解决方案9】:

          只需@OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true)

          删除targetEntity = MyClass.class,效果很好。

          【讨论】:

            【解决方案10】:

            据记载,在 JPA2 之前的 OpenJPA 中,它是 @ElementDependant。

            【讨论】:

              【解决方案11】:

              我使用的是一对一映射,但孩子没有被删除 JPA 给出了外键违规

              使用 orphanRemoval = true 后,问题得到解决

              【讨论】:

              • @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "CHILD_OID") private Child child;
              猜你喜欢
              • 1970-01-01
              • 2013-06-05
              • 2011-02-09
              • 2018-03-31
              • 1970-01-01
              • 2015-10-06
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多