【问题标题】:JPA Inheritance - parent is not deleted with childJPA 继承 - 父级不与子级一起删除
【发布时间】:2017-11-27 13:41:28
【问题描述】:

你能帮我删除继承记录吗?我正在为对象使用实体管理器,当我调用 em.remove(childInstance) 时,只删除了子项,而父项保持未删除。你能告诉我我做错了什么吗?

总表:

@MappedSuperclass
public abstract class General {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", columnDefinition = "serial")
    private Long id;

    // some other columns, getters and setters
}

父表:

@Entity
@Table(name = "PARENT_TABLE")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Parent extends General {

    // some columns and getters and setters
}

儿童班:

@Entity
@Table(name = "CHILD_TABLE")
@OnDelete(action = OnDeleteAction.CASCADE)
public class Child extends Parent {

@ManyToOne(fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@JoinColumn(name = "main_child",
        nullable = true,
        columnDefinition = "integer default 0")
private Child mainChild;

@OnDelete(action = OnDeleteAction.CASCADE)
@OneToMany(fetch = FetchType.LAZY, mappedBy = "child")
private Set<MyObjectA> objects = new HashSet<>();

    @OnDelete(action = OnDeleteAction.CASCADE)
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "id")
    private Set<Child> subChildren = new HashSet<>();

    // some columns and getters and setters
}

MyObjectA 类:

@Entity
@Table(name = "object_a")
public class MyObjectA extends General {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "child_id", nullable = false)
    private Child child;
}

编辑:1 我忘了写其他实体引用子对象,子对象引用自己。

编辑:2 我尝试将这个添加到一对多:

cascade = CascadeType.ALL, orphanRemoval = true

它会返回那个错误

org.postgresql.util.PSQLException:错误:更新或删除表 “父”违反外键约束 “孩子”表上的“xxxxxxxxxxxxxxxxxxxxxxx”

我在数据库中查看该约束是什么,它引用了该脚本:

ALTER TABLE public.child
  ADD CONSTRAINT xxxxxxxxxxxxxxxxxxxxxxx FOREIGN KEY (id)
      REFERENCES public.parent (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION; -- here should be ON DELETE CASCADE

【问题讨论】:

  • 如何检查父级是否被删除?通过查看数据库或分析引用父级的其他实体?
  • 寻找数据库
  • 那我就不知道了。您的设置与我通常使用的设置之间只有一些细微差别:1) 在大多数情况下,我没有 @Table@OnDelete 注释。 2)我使用序列来生成 ID(每个实体表一个,所以 ID 不在我的 General 类中,但在这种情况下将在 Parent 中定义)
  • @JeroenSteenbeeke 检查我的更新,我写了与子表的关系。
  • 也许这个问题+答案有帮助? stackoverflow.com/questions/44474984/…

标签: java hibernate jpa


【解决方案1】:

删除父级可能会失败,因为该父级还有其他子级。通常,为了删除某个孩子的父母,在这种情况下,您还需要删除该孩子的所有兄弟姐妹。

我对你的设计有点困惑 - 如果你真的打算让一些父母和他们的孩子一起移除所有兄弟姐妹 - 你应该

  • 使父/子之间的所有相关关系都是双向的
  • 使父级删除也级联到子级

例如,在孩子中是这样的:

@ManyToOne(cascade=CascadeType.REMOVE)
private Parent parent;

在父母中

@OneToMany(cascade=CascadeType.REMOVE, mappedBy="parent")
private Collection<Child> children;

您的情况

@OneToMany(fetch = FetchType.LAZY, mappedBy = "id")
private Set<Child> subChildren = new HashSet<>();

应该改为

// maps Child to itself bi-dir, note mappedBy changed form "id"
@OneToMany(fetch = FetchType.LAZY, mappedBy = "mainChild", 
              cascade=CascadeType.REMOVE) 
private Set<Child> subChildren = new HashSet<>();

【讨论】:

  • 在父母中我没有任何关系,只有孩子是从父母那里继承的。接下来对于关系,我使用独生子女。所以在物理数据库中,我只有 FK 引用了父级的子级。并且该表具有相同数量的记录。所以当孩子被删除时,也必须是父母。
  • 你有@ManyToOne 单向关系 Child.mainChild。所以这个 mainChild(它扩展了 Parent)可能有其他的孩子。这个对“父”表的更新或删除违反了外键约束……在“子”表上告诉它。
  • 是的,你说得对,但是如果孩子与自己有关系,我怎么能做双向呢?您可以编辑我的相关课程以向我展示如何请吗?
  • 在 Child 中快速浏览一下,subChildren mappedBy 应该不是“id”而是“mainChild”
猜你喜欢
  • 1970-01-01
  • 2021-12-02
  • 2014-01-31
  • 1970-01-01
  • 2018-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
相关资源
最近更新 更多