2017-05-03 161 views
1

我看到很多类似的问题,但还没有找到将结合在一起的结论。级联在JPA @OneToMany中删除与数据库级联外键删除

使用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表将不得不与一个外键约束的Parentid列列parent_id

在该级联删除的外键约束上可能执行的某些操作是delete,set to nulldo nothing。这给出了以下场景组合。

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

所以,关于这个问题。

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

这使EntityManager缓存处于与数据库不一致的状态吗?我认为它是D和E.在这些情况下,您必须自己为子列表中的实例调用remove()

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

回答

0
  • 异常方案:

我觉得B,和E会导致过多的例外,因为外键字段不为空。

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

  • 实现JPA和数据库的一致性

我认为使用A,或F将实现它。在他们两人中,两个层次都会采取相同的行动。