4

I'm seeing a lot of similar questions, but haven't found something conclusive that brings it together.

When using JPA, if you have a @OneToMany relation it can be specified to cascade the REMOVE operation. At the same time, foreign keys can be specified in the database with an action to take if the key base row gets deleted.

JPA example:

@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...

}

In the database, the Child table would then have a column parent_id with a foreign key constraint to the Parent's id column.

Some actions possible on that foreign key constraint for cascading on delete are delete, set to null and do nothing. This gives the following combinations of scenarios.

       JPA | cascade | no cascade |
           | remove  | remove     |
DB FK      |         |            |
-----------+---------+------------|
delete     |    A    |     D      |
-----------+---------+------------|
set null   |    B    |     E      |
-----------+---------+------------|
do nothing |    C    |     F      |
-----------+---------+------------+
  • A: Cascade remove call on parent in JPA, delete children in database on deletion of parent row they have a foreign key to.
  • B: Cascade remove in JPA, set foreign key column in Child table to null in database on parent delete. The nullable in @JoinColumn and/or optional in @ManyToOne probably need to be true/false in this case.
  • C: Cascade remove in JPA, do nothing in the database on a foreign key removal.
  • D: Don't cascade remove in JPA, cascade delete of parent in database.
  • E: Don't cascade remove in JPA, set foreign key column in Child table to null in database on parent delete.
  • F: Don't cascade remove in JPA, do nothing n the database on a foreign key removal.

So, questions about this.

Which of these scenarios leads to exceptions? If figure C would. If you remove a Parent instance via an EntityManager, the call is first done on that instance and then cascaded to the Child instances in the collection property. But trying to remove a parent from the database without first removing related children leads to foreign key violations. Is this correct? Are there other faulty scenarios? Woud A cause issues with trying to remove entities from persistence that have already been removed from the underlying DB?

Which leave the EntityManager cache in an inconsistent state with the database? I reckon it's D and E. In these cases you would have to call remove() for the instances in the child list yourself.

Which setup should you use to enforce data consistency in both the JPA layer and on the database? Will A do the trick? I think B could also work since the database itself will set the foreign key columns to null on deleting a parent (no longer violating constraints) and JPA can then remove the child instances.

G_H
  • 11,739
  • 3
  • 38
  • 82

1 Answers1

0
  • Exception Scenarios:

I think B, and E leads to exceptions too, since the foreign key field not is nullable.

When updating its value with null, there an exception will be raised.

  • To Achieve Consistency between JPA and database:

I think using A, or F will achieve it. In both of them the same actions will be taken on the both layers.