Hibernate - effacer une collection avec all-delete-orphelin et y ajouter des causes cause ConstraintViolationException
J'ai ces entités
class Foo{
Set<Bar> bars;
}
class Bar{
Foo parent;
String localIdentifier;
}
Avec cette cartographie (désolé, pas d'annotations, je suis vieux jeu):
<class name="Foo">
...
<set name="bars" cascade="all-delete-orphan" lazy="false" inverse="true">
<key>...</key>
<one-to-many class="Bar"/>
</set>
</class>
<class name="Bar">
...
<property name="localIdentifier" column="local_identifier"/>
<many-to-one name="parent" column="parent_id" />
</class>
J'ai aussi une contrainte unique sur 2 colonnes: local_identifier
et parent_id
(pas unicité de la contraindre à chaque, mais un seul et unique contraindre contenant à la fois, par exemple, pas 2 lignes avec le même parent et même localIdentifier sont autorisés)
alter table bar add constraint unique_bar unique (parent_id, local_identifier)
Et ce code qui les utilise:
//foo is persistent, foo id = 1
Bars bars = foo.getBars();
bars.clear(); //bars contained 1 item [parent_id = 1, local_identifier = "a"]
Bar newBar = new Bar();
newBar.setParent(foo);
newBar.setLocalIdentifier("a");
bars.add(newBar);
Maintenant, pour une raison quelconque, Hibernate ne pas exécuter les choses dans l'ordre où ils ont été appelés. Il ne veut pas exécuter l' clear()
(effacer) avant de le add()
(insert), mais inversement, il tente d'abord d'insérer, l'obtention d'un ConstraintViolationException
Je sais que l'ajout d'un peu de session.flush()
après bars.clear();
, pourrait résoudre ce problème, mais dans ce cas, je n'ai pas accès à la session dans un non laid.
Est donc flush est la seule solution? ou est-il une version d'Hibernate qui respecte l'ordre des actions?
Mise à jour:
Par la façon dont, en référence à la collection entraînera une HibernateException de https://www.hibernate.org/117.html#A3:
je HibernateException: Ne pas
de déréférencer une collection avec
cascade="all-delete-orphan" Cette
qui va vous arriver si vous chargez un objet avec
une cascade="all-delete-orphan"
collection puis retirez le
référence à la collection. Ne pas
remplacer cette collecte, à l'utilisation clear()
donc, l'orphelin-la suppression de l'algorithme peut
détecter votre changement.
source d'informationauteur Eran Medan
Vous devez vous connecter pour publier un commentaire.
Je suppose qu'il n'y a pas d'alternative à la chasse d'eau
De ici:
Si vous voulez éviter de rinçage de la session ici, essayez de remplacer l'ensemble de la liste (
new List<Bar>()
au lieu deClear()
). Mise en veille prolongée doit effectivement supprimer tous les éléments d'un seul coup avant d'en ajouter de nouveaux. Juste un essai, vous ne savez pas si il fonctionne.Si vous utilisez oracle, vous pouvez également utiliser reportable contraintes de reporter la vérification des contraintes jusqu'à ce que la transaction est validée. Vous ne savez pas si/comment c'est pris en charge par d'autres bases de données.