Violation de contrainte en mode veille prolongée unidirectionnel OneToMany avec cartographie JoinTable et OrderColumn lors de la suppression d'éléments
J'ai un problème lors de la suppression d'éléments d'une liste mappé comme décrit ci-dessus. Voici la cartographie:
@Entity @Table( name = "foo") class Foo { Liste privée bars; @OneToMany @OrderColumn( name = "order_index" ) @JoinTable( name = "foo_bar_map", joinColumns = @JoinColumn( name = "foo_id" ), inverseJoinColumns = @JoinColumn( name = "bar_id" ) ) @Fetch( FetchMode.Sous-sélection ) Liste publique getBars() { retour bars; } }
L'insertion de la Barre-les instances et l'enregistrement de la Foo fonctionne bien, mais lorsque je supprime un élément de la liste et de les enregistrer à nouveau, la contrainte unique sur bar_id dans la table de correspondance est violé. La suite de commandes SQL sont émis par hibernate, et ceux-ci semblent tout à fait bizarre:
JOURNAL: exécuter : suppression de foo_bar_map où foo_id=1$et order_index=$2 DÉTAIL: les paramètres: $1 = '4', $2 = '6' JOURNAL: exécuter S_5: mise à jour foo_bar_map ensemble bar_id=$1 où foo_id=2$et order_index=$3 DÉTAIL: les paramètres: $1 = '88', $2 = '4', $3 = '0' ERREUR: la valeur de clé en double viole la contrainte unique "foo_bar_map_bar_id_key"
L'erreur est parfaitement logique, compte tenu des déclarations générées par Hibernate (il y a cinq éléments dans la liste, j'ai supprimer le premier et Hibernate supprime la rangée de mappage avec le DERNIER indice et la tente pour les mises à jour les autres, en commençant par la première).
Quel est le problème avec la cartographie ci-dessus?
OriginalL'auteur tbk | 2010-10-26
Vous devez vous connecter pour publier un commentaire.
Votre cartographie est totalement valide et fonctionne avec EclipseLink comme JPA 2.0 mise en œuvre (sans le
Fetch
annotation bien sûr), mais au contraire d'échec avec mise en veille prolongée.Voici le DDL avec Hibernate:
Donc, disons
Foo#1
détient une liste avecBar#1
,Bar#2
,Bar#3
, la table de jointure contient:Lors de la dépose, de dire le premier élément de la liste, Hibernate première
delete
la dernière ligne (WTF?) à partir de la table de jointure:Et puis essaie de
update
labar_id
colonne dans la table de jointure au lieu de laorder_index
(WTF!?) afin de refléter la "nouvelle" ordre des éléments dans la liste. La première (schématiquement):où la prochaine étape dans
Évidemment, cette approche n'est pas bonne et ne fonctionne pas en raison de la
unique
contrainte surbar_id
. Plus généralement, pourquoi diable ne Hibernate mess avec lebar_id
au lieu de la mise à jour de laorder_index
de la colonne?Je considère que c'est une Hibernate bug (signalé que
HHH-5694voir HHH-1268 maintenant).Oui, faire de l'association plusieurs-à-plusieurs va supprimer la contrainte d'unicité ("beaucoup"). Mais c'est en effet une solution de contournement, Hibernate doit gérer un un-à-plusieurs correctement. Vous pourriez vouloir voter pour le Tableau de problème 🙂
OriginalL'auteur Pascal Thivent
Généralement lors de l'adhésion par le biais d'une table de jointure de la relation ManyToMany pas OneToMany. Essayez cette
Avec la norme JPA, un unidirectionnelle OneToMany est mappé à l'aide d'une table de jointure (bien que Hibernate permet de tracer sans une table de jointure à l'aide d'un
JoinColumn
, qui est également pris en charge dans JPA 2.0).OriginalL'auteur mR_fr0g
Je suppose que ce que vous avez besoin est correct correspondance inverse.
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/tutorial.html#tutorial-associations-bidirectional
OriginalL'auteur ch4nd4n
Non, je ne pense pas que c'est une hibernate bug, et comme vous pourrez le voir si vous faites des recherches de ce hibernate bug cité par Pascal Thivent est un bug connu depuis 2006 et n'a jamais été résolu.
Pourquoi ?
Parce que je pense que le problème est juste dans les contraintes de la table et de ne pas en mode veille prolongée.
Je ne comprends pas pourquoi il y a une contrainte unique sur bar_id
À l'aide d'un indice d'ordre signifie que votre collection est une Liste (et non pas un Jeu !).
Et une Liste est une collection où vous pouvez spécifier l'index des éléments que vous ajoutez (elle correspond à OrderColumn).
La différence entre une Liste et un Ensemble est que vous, et deux fois les mêmes données (ou plus), mais les mêmes données seront à différents indices.
Alors vous pouvez avoir le même bar_id un autre index, vous n'avez pas à spécifier une contrainte unique sur bar_id.
Et la clé primaire ne peut pas être (foo_id, order_index) cause le modèle de la Liste autoriser les mêmes données à différents indices.
Peut-être que votre PK devrait être (foo_id, bar_id, order_index) ?
Je pense que le problème est dans cette voie 🙂
vrai, il peut être fait par SortedSet docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/...
OriginalL'auteur Nico