JPA: unidirectional multi-channel and cascading deletion

Say I have a unidirectional @ManyToOne relationship, similar to the following:

 @Entity public class Parent implements Serializable { @Id @GeneratedValue private long id; } @Entity public class Child implements Serializable { @Id @GeneratedValue private long id; @ManyToOne @JoinColumn private Parent parent; } 

If I have a parent P and children C 1 ... C n referencing P, is there a clean and beautiful way in JPA to automatically remove children C 1 ... C n when P is deleted (i.e. entityManager.remove(P) )?

I am looking for functionality similar to ON DELETE CASCADE in SQL.

+85
java jpa many-to-one
Aug 25 2018-11-21T00:
source share
6 answers

Relationships in JPA are always unidirectional if you do not connect the parent with the child in both directions. Cascading REMOVE operations from a parent to children require a parent-child relationship (and not just the other way around).

You will need to do this:

  • Either change the @ManyToOne unidirectional connection to @ManyToOne bidirectional, or @OneToMany unidirectional. You can then cascade REMOVE operations so that EntityManager.remove removes the parent and children. You can also specify orphanRemoval as true to remove all orphans when the child in the parent collection is set to null, that is, delete if it is not in any parent collection.
  • Or, specify the foreign key constraint in the child table as ON DELETE CASCADE . You will need to call EntityManager.clear() after calling EntityManager.remove(parent) , because you need to update the persistence context - child entities should not exist in the persistence context after they are deleted in the database.
+67
Aug 26 2018-11-11T00:
source share

If you use hibernate as a JPA provider, you can use the @OnDelete annotation. This annotation will add an ON DELETE CASCADE trigger to the connection, which delegates the removal of children to the database.

Example:

 public class Parent { @Id private long id; } public class Child { @Id private long id; @ManyToOne @OnDelete(action = OnDeleteAction.CASCADE) private Parent parent; } 

With this solution, a one-way relationship from child to parent is enough to automatically remove all children. This solution does not need any listeners, etc. Also, a query, such as DELETE FROM Parent WHERE id = 1, will remove the children.

+78
Jul 21 '16 at 4:59
source share

Create a bi-directional relation, for example:

 @Entity public class Parent implements Serializable { @Id @GeneratedValue private long id; @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE) private Set<Child> children; } 
+13
Jun 18 '12 at 1:28
source share

I saw in unidirectional @ManytoOne, the removal does not work as expected. When the parent is deleted, ideally the child should also be deleted, but only the parent will be deleted, and the child will NOT be deleted and remain an orphan

The following technologies are used: Spring Boot / Spring Data JPA / Hibernate

Sprint Boot: 2.1.2.RELEASE

Spring Data JPA / Hibernate used to remove .eg string

parentRepository.delete(parent)

ParentRepository extends the standard CRUD repository, as shown below ParentRepository extends CrudRepository<T, ID>

Below is my entity class

 @Entity(name = 'child') public class Child { @Id @GeneratedValue private long id; @ManyToOne( fetch = FetchType.LAZY, optional = false) @JoinColumn(name = 'parent_id", nullable = false) @OnDelete(action = OnDeleteAction.CASCADE) private Parent parent; } @Entity(name = 'parent') public class Parent { @Id @GeneratedValue private long id; @Column(nullable = false, length = 50) private String firstName; } 
+1
Feb 11 '19 at 15:57
source share

Use this method to remove only one side.

  @ManyToOne(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY) // @JoinColumn(name = "qid") @JoinColumn(name = "qid", referencedColumnName = "qid", foreignKey = @ForeignKey(name = "qid"), nullable = false) // @JsonIgnore @JsonBackReference private QueueGroup queueGroup; 
0
Sep 09 '19 at 13:47
source share

@Cascade (org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

This annotation worked for me. You can also try

For example: -

  public class Parent{ @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="cct_id") private Integer cct_id; @OneToMany(cascade=CascadeType.REMOVE, fetch=FetchType.EAGER,mappedBy="clinicalCareTeam", orphanRemoval=true) @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private List<Child> childs; } public class Child{ @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="cct_id") private Parent parent; } 
-one
Feb 25 '16 at 9:29
source share



All Articles