Question

J'ai deux classes d'entités annotées de la manière suivante

@Entity
class A {
   @ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
   private List<B> b;
 ..
}

@Entity
class B {
   @ManyToMany(cascade=CascadeType.ALL)
   private List<A> a;
 ..
}

Si je stocke une instance de la classe 'B', les relations sont stockées dans la base de données et le getter de la classe 'A' renverra le sous-ensemble correct de B's. Cependant, si je modifie la liste de B en "A", les modifications ne sont pas stockées dans la base de données?

Ma question est la suivante: comment puis-je faire en sorte que les modifications de l'une ou l'autre classe soient "en cascade"? à l'autre classe?

EDIT: j'ai essayé différentes variantes de suppression du paramètre mappedBy et de définition d'un JoinTable (et de colonnes), mais je n'ai pas trouvé la bonne combinaison.

Était-ce utile?

La solution

La réponse la plus courte semble être que vous ne pouvez pas et que cela a du sens. Dans une association bidirectionnelle plusieurs à plusieurs, un côté doit être maître et est utilisé pour conserver les modifications apportées à la table de jointure sous-jacente. Comme JPA ne gère pas les deux côtés de l'association, vous risquez de vous retrouver avec une situation de mémoire qui ne pourrait pas être rechargée une fois stockée dans la base de données. Exemple:

A a1 = new A();
A a2 = new A();
B b = new B();
a1.getB().add(b);
b.getA().add(a2);

Si cet état pouvait être conservé, vous vous retrouveriez avec les entrées suivantes dans la table de jointure:

a1_id, b_id
a2_id, b_id

Mais lors du chargement, comment JPA aurait-il su que vous aviez l’intention de ne laisser savoir que b à propos de a2 et non a1? et que dire de a2 qui ne devrait pas savoir à propos de b?

C’est pourquoi vous devez conserver vous-même l’association bidirectionnelle (et rendre l’exemple ci-dessus impossible à obtenir, même en mémoire) et JPA ne persistera que sur la base de l’état de l’un de ses côtés.

Autres conseils

Avez-vous spécifié les colonnes de jointure inverse?

@Entity
class A {
   @ManyToMany(mappedBy="A", cascade=CascadeType.ALL)
   private List <B> b;
   ..
}

@Entity 
class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="A_ID")},
       inverseJoinColumns = {@JoinColumn(name="B_ID")}
   )
   private List<A> a; 
   .. 
} 

Cela suppose une table de jointure appelée A_B avec les colonnes A_ID et B_ID.

  

Comme la relation est bidirectionnelle, de même que les mises à jour de l'application   un côté de la relation, l’autre côté devrait également être mis à jour,   et être en phase. En JPA, comme en Java en général , c’est le   la responsabilité de l'application, ou le modèle objet de maintenir   relations. Si votre application ajoute à l'un des côtés d'un   relation, alors il doit ajouter à l'autre côté.

     

Ceci peut être résolu en ajoutant ou en définissant des méthodes dans le modèle d'objet   qui gèrent les deux côtés des relations, de sorte que le code de l'application   n'a pas besoin de s'inquiéter à ce sujet. Il y a deux façons d'aborder cela,   vous pouvez uniquement ajouter le code de maintenance de relation sur un côté   de la relation et n'utilisez le passeur que d'un côté (comme   en protégeant l’autre côté), ou ajoutez-le des deux côtés et assurez-vous   vous évitez une boucle infinie.

Source: OneToMany # Getters_and_Setters

Avez-vous essayé d’ajouter le paramètre mappedBy au champ A de la classe B comme suit

@Entity
class B {
   @ManyToMany(cascade=CascadeType.ALL, mappedBy = "b")
   private List<A> a;
 ..
}

Peut-être qu'il y a une petite erreur dans la réponse de A_M. À mon avis, cela devrait être:

   @Entity
   class B { 
   @ManyToMany 
   @JoinTable (
       name="A_B",
       joinColumns = {@JoinColumn(name="B_ID")},
       inverseJoinColumns = {@JoinColumn(name="A_ID")}
   )
   private List a; 
   .. 
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top