Oublions d'abord Hibernate. Supposons que j'ai deux tables, A et B. Deux transactions mettent à jour les mêmes enregistrements dans ces deux tables, mais txn 1 met à jour B puis A, tandis que txn 2 met à jour A puis B. Il s'agit d'un exemple de blocage typique. La façon la plus courante d'éviter cela est de prédéfinir l'ordre d'acquisition des ressources. Par exemple, nous devons mettre à jour le tableau A puis B.
Retournez à Hibernate. Lorsque nous mettons à jour de nombreuses entités en une seule session, une fois que je vide la session, les modifications de différentes entités vont générer des instructions d'insertion/mise à jour/suppression correspondantes dans DB. Hibernate a-t-il un algorithme pour décider de l'ordre de mise à jour entre les entités? Sinon, comment Hibernate a-t-il utilisé pour éviter la situation de blocage décrite au 1er paragraphe?
Si Hibernate maintient la commande, comment puis-je connaître ou contrôler la commande? Je ne veux pas que ma mise à jour explicite dans les conflits de base de données avec Hibernate, et provoque un blocage.
Le problème que vous décrivez n'est pas géré par la base de données, et d'après mon expérience, il n'est pas entièrement géré par Hibernate non plus.
Vous devez prendre des mesures explicites pour éviter que cela ne soit un problème.
Hibernate fait une partie du travail pour vous. Comme indiqué dans la réponse précédente, Hibernate garantit qu'au sein d'une vidange isolée, les insertions, les suppressions et les mises à jour sont ordonnées de manière à garantir qu'elles seront appliquées dans un ordre réalisable. Voir performExecutions (session EventSource) dans la classe AbstractFlushingEventListener:
Exécutez toutes les commandes SQL (et les mises à jour du cache de deuxième niveau) dans un ordre spécial afin que les contraintes de clé étrangère ne puissent pas être violées:
- Inserts, dans l'ordre où ils ont été effectués
- Mises à jour
- Suppression des éléments de collection
- Insertion d'éléments de collection
- Supprime, dans l'ordre où elles ont été effectuées
Lorsque vous avez des contraintes uniques, il est très important de connaître cet ordre, surtout si vous souhaitez remplacer un enfant un-à-plusieurs (supprimer l'ancien/insérer le nouveau) mais que l'ancien et le nouvel enfant partagent les mêmes contraintes uniques (par exemple, la même adresse e-mail ). Dans ce cas, vous pouvez mettre à jour l'ancienne entrée, au lieu de supprimer/insérer, ou vous pouvez vider après suppression uniquement pour ensuite continuer l'insertion. Pour un exemple plus détaillé, vous pouvez vérifier cet article .
Notez qu'il ne spécifie pas l'ordre des mises à jour. L'examen du code Hibernate m'amène à penser que l'ordre de mise à jour dépendra de l'ordre dans lequel les entités ont été ajoutées au contexte de persistance, [~ # ~] pas [~ # ~] l'ordre dans lequel ils ont été mis à jour. Cela peut être prévisible dans votre code, mais la lecture du code Hibernate ne m'a pas donné le sentiment de me fier à cette commande.
Il y a trois solutions auxquelles je peux penser: