在JPA @OneToMany与数据库级联外键删除中级联删除

时间:2017-05-03 11:13:23

标签: java jpa foreign-keys cascading-deletes

我看到很多类似的问题,但是没有找到一些结论性的东西。

使用JPA时,如果您有@OneToMany关系,则可以指定它级联REMOVE操作。同时,可以在数据库中指定外键,并在删除键基行时执行操作。

JPA示例:

@Entity
public class Parent {

    @Id
    private Long id;
    @OneToMany(cascade = {CascadeType.REMOVE})
    private List<Child> children;
    // getters, setters...

}

@Entity
public class Child {

    @Id
    private Long id;
    @ManyToOne(optional = false)
    @JoinColumn(name = parent_id, nullable = false)
    private Parent parent;
    // getters, setters...

}

在数据库中,Child表将有一个列parent_id,其中包含Parent id列的外键约束。

对于删除级联的外键约束,可能采取的一些操作是deleteset to nulldo nothing。这给出了以下场景组合。

       JPA | cascade | no cascade |
           | remove  | remove     |
DB FK      |         |            |
-----------+---------+------------|
delete     |    A    |     D      |
-----------+---------+------------|
set null   |    B    |     E      |
-----------+---------+------------|
do nothing |    C    |     F      |
-----------+---------+------------+
  • A:在JPA中级联删除对父项的调用,删除父数据库中的子项时,他们有一个外键。
  • B:在JPA中删除Cascade,在父表删除时将Child表中的外键列设置为null。在这种情况下,@ JoinColumn中的nullable和/ optional中的@ManyToOne可能需要为true / false。
  • C:JPA中的级联删除,在删除外键时数据库中不执行任何操作。
  • D:不要在JPA级联删除,在数据库中级联删除父级。
  • E:不要在JPA中级联删除,在父表删除时将Child表中的外键列设置为空。
  • F:不要在JPA中级联删除,在删除外键时不对数据库执行任何操作。

所以,对此有疑问。

以下哪种情况会导致异常?如果图C会出现异常?如果通过Parent删除EntityManager实例,则首先在该实例上完成调用,然后级联到集合属性中的Child实例。但是,在没有先删除相关子项的情况下尝试从数据库中删除父项会导致外键违规。它是否正确?还有其他错误的情况吗? Woud A试图从已经从基础数据库中删除的持久性中删除实体会导致问题吗?

哪个让EntityManager缓存与数据库处于不一致状态?我认为它是D和E.在这些情况下,您必须为实例调用remove()在孩子名单中自己。

您应该使用哪种设置来强制JPA层和数据库中的数据一致性? A会这样做吗?我认为B也可以工作,因为数据库本身会在删除父项时将外键列设置为null(不再违反约束),然后JPA可以删除子实例。

1 个答案:

答案 0 :(得分:0)

  • 例外情景:

我认为B和E也会导致异常,因为外键字段不可为空。

使用null更新其值时,将引发异常。

  • 在JPA和数据库之间实现一致性

我认为使用A或F会实现它。在这两个方面,将对这两个层采取相同的行动。