1

J'utilise Hibernate 2.6 avec hibernate-entitymanager. J'essaie d'attraper et de gérer des situations lorsque 2 transactions sont en conflit sur un objet. Voici ce qui se passe:Comment détecter les conflits de transaction avec Hibernate?

Deux threads mettent à jour un seul objet avec un champ @Version. Le thread qui perd la course enregistre les logs StaleObjectStateException sur flush. L'exception n'est pas levée, elle est simplement enregistrée. Je suppose que la transaction est annulée à ce moment-là. Ensuite, lorsque le thread tente d'effectuer la validation, il échoue avec RollbackException. Je n'ai pas trouvé de moyen de savoir dans le code pourquoi la transaction est annulée.

Y at-il un moyen d'attraper et de gérer de telles situations dans le code? Fondamentalement, je veux attraper StaleObjectStateException, mais le problème est - il n'est pas levé.

MISE À JOUR: La chose que je suis en train d'accomplir du point de vue des yeux des oiseaux est la suivante:

J'ai une application J2EE fonctionnant sous JBoss. Il a quelques services invoqués par minuterie interne et ceux invoqués à partir de l'interface utilisateur. Il a également une entité critique. Je dois m'assurer que des threads différents ne peuvent pas mettre à jour simultanément des objets de cette classe d'entités, car cela peut entraîner une incohérence de données. C'est pourquoi je suis en train de mettre en œuvre un verrouillage optimiste.

Lorsqu'un problème de verrouillage optimistick se produit, j'essaie de gérer cette situation en général. Je veux l'attraper au niveau très élevé et montrer un message d'utilisateur valide (dans mon cas le plus haut niveau est ExceptionMapper pour RestEasy). Le problème est - quand j'attrape RollbackException - il est déjà trop tard.

Je ne vidange pas manuellement. La plupart de mes EJB utilisent CMT et les sessions sont vidées automatiquement.

+0

J'ai mis à jour ma réponse en fonction de votre clarification – ChssPly76

Répondre

0

Jetez un oeil à NHProf. Il peut vous aider avec toutes sortes de choses liées au profilage de Nhibernate.

+0

J'utilise Hibernate pour Java, pas NHibernate. Et je la question n'est pas sur le profilage, il s'agit de situations exceptionnelles de manipulation – artemb

+0

un profileur vous aidera à détecter de tels problèmes et à les réduire. NHProf -does- supporte aussi Hibernate. –

2

Artem,

Pourriez-vous expliquer brièvement ce qu'il vous est essayez d'atteindre? Vue aérienne, évidemment - comme est-ce (invoqué) code de l'interface utilisateur? Ou est-ce un processus côté serveur (donc vous auriez des contrôles directs sur les threads)? La raison pour laquelle je demande est que je reçois un sentiment (peut-être incorrect) de ceci et de vos autres questions connexes que vous essayez d'utiliser un verrouillage optimiste pour quelque chose pour lequel il n'a pas été conçu et qui cause tout le problème.

En ce qui concerne StaleObjectStateException va, il est très certainement lancé à la fois DefaultFlushEventListener et AutoFlushEventListener qui gèrent les vidages explicites/implicites. Appelez-vous flush() manuellement? Dans le cas contraire, peut-être l'exception est pris/connecté par code wrapper autour de rinçage automatique (printemps? TransactionManager? EntityManager?)

Mise à jour

Merci pour clarifier la question. Je suis encore un peu difficile de savoir si vous voulez éviter plusieurs threads de modifier simultanément la même entité ou empêcher plusieurs utilisateurs d'essayer de modifier en même temps il.

Le scénario précédent peut être géré par un verrouillage optimiste; Cependant, sans flush() explicite, il devient non déterministe (le thread qui a fait la modification en premier ne peut pas être vidé/validé en premier). Voir ma réponse à this question pour plus de détails. Un autre problème avec le vidage automatique est ce que vous êtes en train de rencontrer: la vérification de la version échouée n'est pas détectée avant le vidage et, si cette vidage coïncide avec la tentative de validation de la transaction, l'exception levée est RollbackException. De toute façon, toute la transaction est annulée.

Ce scénario (empêchant les utilisateurs de modifier) ​​ne peut PAS être géré par un verrouillage optimiste. Vous devrez implémenter le verrouillage pessimiste à la place - au niveau de la base de données ou de l'application. En d'autres termes, le processus est le suivant:

  1. utilisateur souhaite modifier l'entité
  2. vérifier si le verrouillage existe sur l 'entité
  3. OUI - interdire l'édition (permet en lecture seule voir?)
  4. NO - entité de verrouillage , autorise l'édition
  5. valider (annuler) les modifications; verrou de libération

Assurez-vous d'expirer les verrous existants après une certaine période d'inactivité si vous utilisez cette approche.


simultanément la modification est pas vraiment exact dans ce cas (c'est ce que les transactions sont pour); nous parlons d'empêcher un thread d'écraser les modifications d'un autre basé sur une version plus ancienne.

+0

Merci. J'ai mis à jour la question avec l'information que vous avez demandée. – artemb

+0

J'essaie d'empêcher plusieurs threads de modifier simultanément. Empêchant exactement un thread d'écraser les modifications d'un autre basé sur une version plus ancienne. Alors, vos conseils sont-ils vidés manuellement? Seulement de cette façon, je peux atteindre mon objectif? – artemb

+0

Considérez ceci: les threads T1 et T2 lisent votre entité en même temps, la modifient, puis T1 l'enregistre et T2 l'enregistre. Avec le rinçage automatique, vous ne savez pas à qui les modifications (T2 ou T1) vont être vidées en premier. En outre, tant que les modifications ne sont pas vidées (et/ou les transactions validées en fonction de l'isolation), l'autre thread ne saura même pas que la version de l'objet a changé. Vous obtenez donc uniquement l'erreur lorsque la transaction échoue et est annulée. Si vous vous souciez de l'ordre de modification ou si vous souhaitez obtenir une exception au début, vous devez vider manuellement. – ChssPly76

Questions connexes