web-dev-qa-db-fra.com

JPA + Hibernate + Spring + OneToMany delete cascade

J'ai lu quelques questions connexes mais ce n'est pas exactement le même problème que le mien.

J'utilise JPA + Hibernate + Spring et je veux faire quelque chose que je ne sais pas si c'est possible juste avec config.

J'ai mes classes de domaine avec une relation plus ou moins compliquée. Il existe de nombreux éléments qui sont liés à un élément (comme s'il s'agissait d'un arbre, de nombreux éléments sont les fils d'un élément).

Quelque chose comme:

@Entity
class Foo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Foo parentNode;
    ...
}

Qui obtiendra une table comme:

Foo id    parent_id
1
2         1 
3         1

Lorsque je supprime une ligne avec id = 1, je veux supprimer des lignes avec id = 2 et id = 3 (cela peut être récursif, les éléments avec parent_id = 2 et parent_id = 3 seraient également supprimés).

Pour certaines restrictions, je ne peux avoir que la relation du côté fils avec la référence parent_id.

Ma question est: est-il possible de le faire avec la configuration JPA ou Hibernate ou dois-je faire une fonction récursive pour supprimer tous les enfants et tous les parents?

J'ai essayé avec:

@OneToMany(name = "PARENT_ID", cascade = CascadeType.REMOVE)

Et j'ai lu que peut-être en utilisant des annotations Hibernate.

Si quelqu'un peut me donner un indice, je suis perdu à ce stade.

Modifier 1

Serait-il possible de faire comme:

@Entity
class Foo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    @JoinColumn(name="PARENT_ID")
    private Foo parentNode;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "parentNode", cascade = CascadeType.REMOVE, orphanRemoval = true)
    private Set<Foo> childs = new LinkedHashSet<Foo>();
    ...
}

Garder la table telle quelle, avec le fk au parent? J'ai essayé mais je reçois toujours la même erreur, la restriction fk a été violée.

Modifier 2

Enfin résolu avec:

@Entity
class Foo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "PARENT_ID")
    private Foo parentNode;

    @OneToMany(mappedBy = "parentNode", cascade = CascadeType.REMOVE)
    private Set<Foo> childs = new LinkedHashSet<Foo>();
    ...
}

Cette @OneToMany est nécessaire même si nous faisons le mappage dans notre BBDD en ne référant qu'à l'ID parent.

Maintenant, lorsque nous supprimons un Foo avec des enfants, ses enfants seront également supprimés.

Merci pour votre temps et bons conseils!

21
Garci García

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 pas seulement le contraire).

Donc, ici, vous devez changer la relation unidirectionnelle en bidirectionnelle.

pour plus de détails se référer ce lien.

24
Harshal Patil

Regardez orphanRemoval option:

@OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true)

Voici explication complète à propos de CascadeType.REMOVE et orphanRemoval.

Bonne chance!

20
jmvivo