2008-09-17 9 views
17

Mi comprensión de Hibernate es que los objetos que 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.Cuando Hibernate vacía una sesión, ¿cómo decide qué objetos de la sesión están sucios?

¿Cómo decide Hibernate qué objetos están "sucios" y necesitan ser escritos?

¿Los proxies generados por las asignaciones de intercepción de Hibernate a los campos, y agregan el objeto a una lista sucia en la sesión?

¿Hibernate observa cada objeto de la Sesión y lo compara con el estado original del objeto?

¿O algo completamente diferente?

Respuesta

22

Hibernate hace/puede usar la generación de bytecode (CGLIB) para que sepa que un campo está sucio tan pronto como llame al setter (o incluso asigne el campo afaict).

Esto inmediatamente marca ese campo/objeto como sucio, pero no reduce la cantidad de objetos que deben revisarse con suciedad durante el lavado. Todo lo que hace es impactar la implementación de org.hibernate.engine.EntityEntry.requiresDirtyCheck(). Es todavía hace una comparación de campo por campo para comprobar 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 la credibilidad que se agrega. Los puntos de interés son:

  • SessionImpl.flush() desencadena un evento onFlush().
  • SessionImpl.list() llamadas autoFlushIfRequired() que activan un evento onAutoFlush(). (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) en flushEntities().
  • Ese bucles sobre cada entidad en la sesión (source.getPersistenceContext().getEntityEntries()) llamando al DefaultFlushEntityEventListener.onFlushEntity().
  • Eventualmente terminará en dirtyCheck(). Ese método hace algunas optimizaciones wrt a CGLIB banderas sucias, pero todavía hemos terminado bucle sobre cada entidad.
+0

Por favor, explique mejor: si la bandera sucia no reduce la cantidad de objetos que deben ser revisados, ¿cuál es su utilidad? Furtermore en la fuente veo dos banderas sucias diferentes: una en AbstractFieldInterceptor y la comprueba EntityEntry.requiresDirtyCheck(), otra en AbstractPersistentCollection y se comenta que "las colecciones detectan los cambios realizados a través de su interfaz pública y se marcan tan sucios como un rendimiento optimización "(no sé dónde está marcado en el código). – Pino

+0

@Matt Quail, no pude encontrar banderas sucias de las que está hablando, solo hay una que se puede usar solo si se usa la instrumentación bytecode de compilación. –

5

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).

+0

En Hibernate, la situación es cómo se describe: una comparación de atributo por atributo de objetos de instantánea con los objetos de sesión. Esto está en contraste con Datanucleus (en el modo JDO o JPA), donde la mejora de su código de bytes le permite hacer cosas muy inteligentes y de alto rendimiento, como agregar una bandera sucia a cada clase persistente. Lo que esto significa es que durante una descarga en Datanucleus la suciedad de cualquier objeto es una simple verificación de la bandera sucia. No necesita ser Einstein para averiguar por qué, con un modelo de dominio orientado a objetos no trivial, por qué el lavado de Hibernate lleva mucho más tiempo. – Volksman

1

Echa un vistazo a org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck Cada elemento en la sesión va a este método para determinar si está sucio o no mediante la comparación con una versión intacta (uno de la caché o uno de la base de datos).

1

Hibernate default dirty checking mechanism recorrerá 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:

Default automatic dirty checking

Cuestiones relacionadas