Disons que j'ai une relation unidirectionnelle @ManyToOne
comme celle-ci:
@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;
}
Si j'ai un parent P et des enfants C1... Cn En se référant à P, existe-t-il un moyen propre et attrayant dans JPA de supprimer automatiquement les enfants C1... Cn quand P est retiré (c'est-à-dire entityManager.remove(P)
)?
Ce que je recherche, c'est une fonctionnalité similaire à ON DELETE CASCADE
en SQL.
Les relations dans JPA sont toujours unidirectionnelles, sauf si vous associez le parent à l'enfant dans les deux sens. Les opérations REMOVE en cascade du parent à l'enfant nécessiteront une relation du parent à l'enfant (et non l'inverse).
Vous devrez donc faire ceci:
@ManyToOne
en un @ManyToOne
bidirectionnel ou un @OneToMany
unidirectionnel. Vous pouvez ensuite mettre en cascade les opérations REMOVE afin que EntityManager.remove
supprime le parent et les enfants. Vous pouvez également spécifier orphanRemoval
en tant que true pour supprimer tous les enfants orphelins lorsque l'entité enfant de la collection parent est définie sur null, c'est-à-dire supprimer l'enfant s'il n'est présent dans la collection d'aucun parent.ON DELETE CASCADE
. Vous devrez appeler EntityManager.clear()
après avoir appelé EntityManager.remove(parent)
car le contexte de persistance doit être actualisé - les entités enfants ne sont pas supposées exister dans le contexte de persistance après avoir été supprimées de la base de données.Si vous utilisez hibernate en tant que fournisseur JPA, vous pouvez utiliser l'annotation @OnDelete. Cette annotation ajoutera à la relation le déclencheur ON DELETE CASCADE , qui délègue la suppression des enfants à la base de données.
Exemple:
public class Parent {
@Id
private long id;
}
public class Child {
@Id
private long id;
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE)
private Parent parent;
}
Avec cette solution, une relation unidirectionnelle de l’enfant au parent suffit pour supprimer automatiquement tous les enfants. Cette solution ne nécessite aucun écouteur, etc. De plus, une requête telle que DELETE FROM Parent WHERE id = 1 supprimera les enfants.
Créez une relation bidirectionnelle, comme ceci:
@Entity
public class Parent implements Serializable {
@Id
@GeneratedValue
private long id;
@OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
private Set<Child> children;
}