domingo, 16 de octubre de 2011

Identidad del objeto en hibernate


Una aplicación puede acceder simultáneamente al mismo estado persistente en dos Sessiones diferentes. Sin embargo, una instancia de una clase persistente nunca se comparte entre dos instancias de Session. Por lo tanto, existen dos nociones diferentes de identidad:



Identidad de Base de Datos
foo.getId().equals( bar.getId() )

Identidad JVM
foo==bar

Para los objetos unidos a una Session en particular (por ejemplo, en el ámbito de una Session) las dos nociones son equivalentes y la identidad de la JVM para la identidad de la base de datos se encuentra garantizada por Hibernate. Mientras la aplicación acceda simultáneamente al "mismo" objeto (identidad persistente) en dos sesiones diferentes, las dos instancias serán realmente "diferentes" (identidad JVM). Los conflictos se resuelven usando un enfoque optimista y el versionado automático.

Este enfoque deja que Hibernate y la base de datos se preocupen de la concurrencia. Además provee la mejor escalabilidad, ya que garantizando la identidad en unidades de trabajo monohilo no necesitan bloqueos caros u otros medios de sincronización. La aplicación no necesita sincronizar sobre ningún objeto, siempre que se mantenga un solo hilo por Session.

Dentro de una Session la aplicación puede usar con seguridad == para comparar objetos. Sin embargo, una aplicación que usa == fuera de una Session, podría ver resultados inesperados. Esto podría ocurrir incluso en sitios algo inesperados. Por ejemplo, si pone dos instancias separadas dentro del mismo Set ambas podrían tener la misma identidad de la base de datos (por ejemplo, representar la misma fila). Sin embargo, la identidad JVM, por definición, no está garantizada para las instancias en estado separado.

El desarrollador tiene que sobrescribir los métodos equals() y hashCode() en las clases persistentes e implementar su propia noción de igualdad de objetos. Nunca se debería usar el identificador de la base de datos para implementar la igualdad. Use una clave de negocio, una combinación de atributos únicos, usualmente inmutables. El identificador de la base de datos cambiará si un objeto transitorio es hecho persistente. Si la instancia transitoria (usualmente junto a las instancias separadas) es mantenida en un Set, cambiar el código hash rompe el contrato del Set. Los atributos para las claves empresariales no tienen que ser tan estables como las claves principales de la base de datos, sólo tiene que garantizar estabilidad en tanto los objetos estén en el mismo Set.

Este no es problema de Hibernate, sino que simplemente se tiene que implementar la identidad y la igualdad de los objetos Java.