Quand Hibernate vide une session, comment décide-t-il quels objets de la session sont sales?

StackOverflow https://stackoverflow.com/questions/82429

Question

D'après ma compréhension d'Hibernate, les objets chargés à partir de la base de données sont ajoutés à la session. À différents moments, en fonction de votre configuration, la session est vidée. À ce stade, les objets modifiés sont écrits dans la base de données.

Comment Hibernate détermine-t-il quels objets sont "sales" et doivent être écrits?

Les mandataires générés par Hibernate interceptent-ils les affectations aux champs et ajoutent-ils l'objet à une liste non-conforme de la session?

Ou Hibernate examine-t-il chaque objet de la session et le compare-t-il à son état d'origine?

Ou quelque chose de complètement différent?

Était-ce utile?

La solution

Hibernate utilise / peut utiliser la génération de bytecode (CGLIB) pour qu’il sache qu’un champ est sale dès que vous appelez le poseur (ou même que vous l’affectez au champ afaict).

Ceci marque immédiatement ce champ / objet comme sale, mais ne réduit pas le nombre d'objets devant être vérifiés sale lors du vidage. Tout ce que cela fait est un impact sur la mise en œuvre de org.hibernate.engine.EntityEntry.requiresDirtyCheck () . Il still effectue une comparaison champ par champ pour vérifier l’état de saleté.

Je dis ce qui précède, basé sur un chalut récent dans le code source (3.2.6GA), quelle que soit la crédibilité que cela ajoute. Les points d'intérêt sont:

  • SessionImpl.flush () déclenche un événement onFlush () .
  • SessionImpl.list () appelle autoFlushIfRequired () , ce qui déclenche un événement onAutoFlush () . (sur les tables d’intérêt). C'est-à-dire que les requêtes peuvent invoquer un flush. Fait intéressant, il n'y a pas de flush s'il n'y a pas de transaction.
  • Ces deux événements finissent par se retrouver dans AbstractFlushingEventListener.flushEverythingToExecutions () , ce qui aboutit (parmi d'autres emplacements intéressants) à flushEntities () .
  • Cela boucle sur toutes les entités de la session ( source.getPersistenceContext (). getEntityEntries () ) appelant DefaultFlushEntityEventListener.onFlushEntity () .
  • Vous finissez par vous retrouver dans dirtyCheck () . Cette méthode effectue certaines optimisations par rapport aux indicateurs modifiés CGLIB, mais nous avons toujours fini par boucler toutes les entités.

Autres conseils

Hibernate prend un instantané de l’état de chaque objet chargé dans la session. Au flush, chaque objet de la session est comparé à l'instantané correspondant pour déterminer ceux qui sont sales. Les instructions SQL sont émises selon les besoins et les instantanés sont mis à jour pour refléter l'état des objets Session (désormais propres).

Jetez un coup d’œil à org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck Chaque élément de la session utilise cette méthode pour déterminer si elle est sale ou non en comparant avec une version non modifiée (une du cache ou une de la base de données).

Le mécanisme de vérification sale par défaut d'Hibernate traverse les entités actuellement rattachées. et associez toutes les propriétés à leurs valeurs initiales au moment du chargement.

Vous pouvez mieux visualiser ce processus dans le diagramme suivant:

Vérification automatique et sale

Ces réponses sont incomplètes (au mieux, je ne suis pas un expert ici). Si vous avez une entité Hib Man dans votre session, vous n'y faites rien, vous pouvez toujours obtenir une mise à jour publiée lorsque vous appelez save (). quand? quand une autre session met à jour cet objet entre votre charge () et save (). voici mon exemple: hibernate définit un indicateur incorrect (et une mise à jour des problèmes) même si le client n'a pas changé de valeur

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top