Mapeo de Componentes La noción de un componente es reusada en muchos contextos diferentes, para propósitos diferentes, a través de Hibernate. Objetos dependientes Un componente es un objeto contenido que es persistido como un tipo de valor, no una referencia de entidad. El término "componente" hace referencia a la noción orientada a objetos de composición (no a componentes a nivel de arquitectura). Por ejemplo, podrías modelar una persona como: Ahora Name puede ser persistido como un componente de Person. Observa que Name define métodos getter y setter para sus propiedades persistentes, pero no necesita declarar ninguna interface ni propiedades identificadoras. Nuestro mapeo de Hibernate se vería así: ]]> La tabla person tendría las columnas pid, birthday, initial, first y last. Como todos los tipos de valor, los componentes no soportan referencias compartidas. En otras palabras, dos personas pueden tener el mismo nombre, pero los dos objetos persona contendrían dos objetos nombre independientes, sólo "iguales" en valor. La semántica de valor nulo de un componente es ad hoc. Cuando se recargue el objeto contenedor, Hibernate asumirá que si todas las columnas del componente son nulas, el componente entero es nulo. Esto debe estar bien para la mayoría de propósitos. Las propiedades de un componentes pueden ser de cualquier tipo de Hibernate (colecciones, muchos-a-uno, asociaciones, otros componentes, etc). Los componentes anidados no deben ser considerados un uso exótico. Hibernate está concebido para soportar un modelo de objetos granularizado en fino. El elemento <component> permite un subelemento <parent> que mapee una propiedad de la clase del componente como una referencia de regreso a la entidad contenedora. ]]> Colecciones de objetos dependientes Las colecciones de componentes están soportadas (por ejemplo, un array de tipo Name). Declara tu colección de componentes remplazando la etiqueta <element> por una etiqueta <composite-element>. ]]> Nota: si defines un Set de elementos compuestos, es muy importante implementar equals() y hashCode() correctamente. Los elementos compuestos pueden contener componentes pero no colecciones. Si tu elemento compuesto contiene a su vez componentes, usa la etiqueta <nested-composite-element>. Este es un caso bastante exótico - una colección de componentes que a su vez tienen componentes. A esta altura debes estar preguntándote si una asociación uno-a-muchos es más apropiada. Intenta remodelar el elemento compuesto como una entidad - pero observa que aunque el modelo Java es el mismo, el modelo relacional y la semántica de persistencia siguen siendo ligeramente diferentes. Por favor observa que un mapeo de elemento compuesto no soporta propiedades nulables si estás usando un <set>. Hibernate tiene que usar cada columna para identificar un registro al borrar objetos (no hay una columna clave primaria separada en la tabla del elemento compuesto), lo que es imposible con valores nulos. Tienes que, o bien usar sólo propiedades no nulas en un elemento compuesto o elegir un <list>, <map>, <bag> o <idbag>. Un caso especial de un elemento compuesto es un elemento compuesto con un elemento anidado <many-to-one>. Un mapeo como este te permite mapear columnas extra de una tabla de asociación muchos-a-muchos a la clase del elemento compuesto. La siguiente es una asociación muchos-a-muchos de Order a Item donde purchaseDate, price y quantity son propiedades de la asociación: .... ]]> Por supuesto, no puede haber una referencia a la compra del otro lado para la navegación bidireccional de la asociación. Recuerda que los componentes son tipos de valor no permiten referencias compartidas. Una sola Purchase puede estar en el conjunto de una Order, pero no puede ser referenciada por el Item al mismo tiempo. Incluso son posibles las asociaciones ternarias (o cuaternarias, etc): .... ]]> Los elementos compuestos pueden aparecer en consultas usando la misma sintáxis que las asociaciones a otras entidades. Componentes como índices de Map El elemento <composite-map-key> te permite mapear una clase componente como la clave de un Map. Asegúrate que sobrescribes hashCode() y equals() correctamente en la clase componente. Componentes como identificadores compuestos Puedes usar un componente como un identidicador de una clase entidad. Tu clase componente debe satisfacer ciertos requerimientos: Debe implementar java.io.Serializable. Debe re-implementar equals() y hashCode(), consistentemente con la noción de base de datos de igualdad de clave compuesta. Nota: en Hibernat3, el segundo requerimiento no es absolutamente un requerimiento rígido de Hibernate. Pero de todas formas, házlo. No puedes usar un IdentifierGenerator para generar claves compuestas. La aplicación debe, en cambio, asignar sus propios identificadores. Usa la etiqueta <composite-id> (con elementos anidados <key-property>) en lugar de la usual declaración <id>. Por ejemplo, la clase OrderLine tiene una clave primaria que depende de la clave primaria (compuesta) de Order. .... ]]> Ahora, cualquier clave foránea que referencie la tabla de OrderLine es también compuesta. Debes declarar esto en tus mapeos de otras clases. Una asociación a OrderLine sería mapeado así: ]]> (Nota que la etiqueta <column> es una alternativa al atributo column en cualquier sitio.) Una asociación muchos-a-muchos a OrderLine también usa la clave foránea compuesta: ]]> La colección de OrderLines en Order usaría: ]]> (El elemento <one-to-many>, como es usual, no declara columnas.) Si OrderLine posee una colección por sí misma, tiene también una clave foránea compuesta. .... .... ... ]]> Componentes dinámicos Puedes incluso mapear una propiedad de tipo Map: ]]> La semántica de un mapeo <dynamic-component> es ídentica a la de <component>. La ventaja de este tipo de mapeos es la habilidad para determinar las propiedades reales del bean en tiempo de despliegue, sólo con editar el documento de mapeo. La manipulación del documento de mapeo en tiempo de ejecución es también posible, usando un analizador DOM. Incluso mejor, puedes acceder (y cambiar) el metamodelo de tiempo de configuración de Hibernate por medio del objeto Configuration.