java - rojeru - Cuando Hibernate vacía una sesión, ¿cómo decide qué objetos de la sesión están sucios?
rojeru san (5)
Mi comprensión de Hibernate es que a medida que los objetos se cargan desde el DB, se agregan a la sesión. En varios puntos, dependiendo de su configuración, la sesión se vacía. En este punto, los objetos modificados se escriben en la base de datos.
¿Cómo decide Hibernate qué objetos son "sucios" y necesitan ser escritos?
¿Los proxies generados por las asignaciones de intercepción Hibernate a los campos, y agregar el objeto a una lista sucia en la sesión?
¿O Hibernate observa cada objeto en la Sesión y lo compara con el estado original de los objetos?
¿O algo completamente diferente?
Eche un vistazo a org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck. Cada elemento de la sesión va a este método para determinar si está sucio o no comparando con una versión intacta (una del caché o una de la base de datos).
Hibernate toma una instantánea del estado de cada objeto que se carga en la sesión. En color, cada objeto en la sesión se compara con su instantánea correspondiente para determinar cuáles están sucios. Las sentencias de SQL se emiten según sea necesario y las instantáneas se actualizan para reflejar el estado de los objetos de sesión (ahora limpios).
Hibernate puede / puede usar la generación de bytecode (CGLIB) para que sepa que un campo está sucio tan pronto como se llama al setter (o incluso se asigna al campo afaict).
Esto inmediatamente marca ese campo / objeto como sucio, pero no reduce la cantidad de objetos que deben ser verificados con suciedad durante el enjuague. Todo lo que hace es impactar la implementación de org.hibernate.engine.EntityEntry.requiresDirtyCheck()
. Todavía hace una comparación de campo por campo para verificar la suciedad.
Digo lo anterior sobre la base de una red de arrastre reciente a través del código fuente (3.2.6GA), con cualquier credibilidad que se agregue. Puntos de interés son:
-
SessionImpl.flush()
desencadena un eventoonFlush()
. -
SessionImpl.list()
llama aautoFlushIfRequired()
que desencadena un eventoonAutoFlush()
. (en las tablas de interés). Es decir, las consultas pueden invocar un color. Curiosamente, no se produce una descarga si no hay ninguna transacción. - Ambos eventos finalmente terminan en
AbstractFlushingEventListener.flushEverythingToExecutions()
, que termina (entre otras ubicaciones interesantes) enflushEntities()
. - Eso recorre todas las entidades de la sesión (
source.getPersistenceContext().getEntityEntries()
) llamando aDefaultFlushEntityEventListener.onFlushEntity()
. - Eventualmente terminas en
dirtyCheck()
. Ese método hace algunas optimizaciones wrt a CGLIB banderas sucias, pero todavía hemos terminado bucle sobre cada entidad.
El mecanismo de verificación sucia por defecto de Hibernate atravesará las entidades adjuntas actuales y unirá todas las propiedades con sus valores iniciales de tiempo de carga.
Puede visualizar mejor este proceso en el siguiente diagrama:
Estas respuestas son incompletas (en el mejor de los casos, no soy un experto aquí). Si tiene una entidad hib man en su sesión, no tiene NADA, aún puede obtener una actualización cuando llama a save () en ella. cuando? cuando otra sesión actualiza ese objeto entre su load () y save (). aquí está mi ejemplo de esto: hibernate establece un indicador sucio (y emite actualizaciones) aunque el cliente no cambió el valor