Articles

Tutorial de Hibernación de Anotación de Uno a Muchos

Introducción

Este tutorial de Hibernación rápida nos llevará a través de un ejemplo de asignación de uno a muchos utilizando anotaciones JPA, una alternativa a XML.

También aprenderemos qué son las relaciones bidireccionales, cómo pueden crear inconsistencias y cómo la idea de propiedad puede ayudar.

Más información:

Bota de resorte con Hibernación

Una introducción rápida y práctica para integrar la bota de resorte y la Hibernación/JPA.
Leer más →

Una Visión general de los Identificadores en Hibernate/JPA

Aprender cómo asignar identificadores de entidad con Hibernate.
Leer más →

Descripción

Simplemente, uno-a-muchos asignación significa que una fila de una tabla se asignan a varias filas de otra tabla.

Echemos un vistazo al siguiente diagrama de relación de entidades para ver una asociación de uno a muchos:

Para este ejemplo, implementaremos un sistema de carrito donde tenemos una tabla para cada carrito y otra tabla para cada elemento. Un carro puede tener muchos artículos, así que aquí tenemos un mapeo de uno a muchos.

La forma en que esto funciona a nivel de base de datos es que tenemos un cart_id como clave primaria en la tabla cart y también un cart_id como clave externa en los elementos.

La forma en que lo hacemos en código es con @OneToMany.

Asignemos la clase Cart al objeto Items de una manera que refleje la relación en la base de datos:

public class Cart { //... @OneToMany(mappedBy="cart") private Set<Items> items; //...}

También podemos agregar una referencia a Cart en Items usando @ManyToOne, haciendo de esta una relación bidireccional. Bidireccional significa que podemos acceder a los artículos de los carros, y también a los carros de los artículos.

La propiedad mappedBy es lo que usamos para indicar a Hibernar qué variable estamos utilizando para representar la clase padre en nuestra clase hija.

Se utilizan las siguientes tecnologías y bibliotecas para desarrollar una aplicación de Hibernación de muestra que implementa la asociación uno a muchos:

  • JDK 1.8 o posterior
  • Hibernate 5
  • Maven 3 o posterior
  • Base de datos H2

Setup

3.1. Configuración de la base de datos

A continuación se muestra nuestro script de base de datos para tablas de Carrito y Artículos. Usamos la restricción de clave foránea para la asignación de uno a muchos:

La configuración de nuestra base de datos está lista, así que pasemos a crear el proyecto de ejemplo de Hibernación.

3.2. Dependencias Maven

Luego agregaremos las dependencias de controladores Hibernate y H2 a nuestro pom.archivo xml. La dependencia de Hibernación utiliza el registro de JBoss y se agrega automáticamente como dependencias transitivas:

  • Hibernación versión 5.2.7.Versión final del controlador H2
  • 1.4.197

Visite el repositorio central de Maven para conocer las últimas versiones de Hibernate y las dependencias H2.

3.3. Configuración de Hibernate

Aquí está la configuración de Hibernate:

3.4. Clase HibernateAnnotationUtil

Con la clase HibernateAnnotationUtil, solo necesitamos hacer referencia al nuevo archivo de configuración de Hibernación:

Los Modelos

Las configuraciones relacionadas con la asignación se realizarán utilizando anotaciones JPA en las clases modelo:

@Entity@Table(name="CART")public class Cart { //... @OneToMany(mappedBy="cart") private Set<Items> items; // getters and setters}

Tenga en cuenta que la anotación @OneToMany se utiliza para definir la propiedad en la clase Items que se utilizará para asignar la variable mappedBy. Es por eso que tenemos una propiedad llamada «cart» en la clase Items:

También es importante tener en cuenta que la anotación @ManyToOne está asociada con la variable Cart class. la anotación @ JoinColumn hace referencia a la columna asignada.

En Acción

En el programa de prueba, estamos creando una clase con un método main() para obtener la Sesión de Hibernación y guardar los objetos del modelo en la base de datos implementando la asociación uno a muchos:

Esta es la salida de nuestro programa de prueba:

La Anotación @ManyToOne

Como hemos visto en la sección 2, puede especificar una relación de varios a uno usando la anotación @ManyToOne. Una asignación de varios a uno significa que muchas instancias de esta entidad se asignan a una instancia de otra entidad, muchos elementos en un carrito.

La anotación @ ManyToOne también nos permite crear relaciones bidireccionales. Cubriremos esto en detalle en las siguientes subsecciones.

6.1. Inconsistencias y Propiedad

Ahora, si el Carrito hacía referencia a Artículos, pero los Artículos a su vez no hacían referencia al Carrito, nuestra relación sería unidireccional. Los objetos también tendrían una consistencia natural.

En nuestro caso, sin embargo, la relación es bidireccional, lo que conlleva la posibilidad de inconsistencia.

Imaginemos una situación en la que un desarrollador quiere agregar item1 a cart y item2 a cart2, pero comete un error para que las referencias entre cart2 y item2 se vuelvan inconsistentes:

Como se muestra arriba, item2 hace referencia a cart2, mientras que cart2 no hace referencia a item2, y eso es malo.

¿Cómo debe hibernarse para guardar el ítem2 en la base de datos? ¿La clave externa de item2 hará referencia a cart1 o cart2?

Resolvemos esta ambigüedad utilizando la idea de un lado propietario de la relación; las referencias que pertenecen al lado propietario tienen prioridad y se guardan en la base de datos.

6.2. Elementos como el Lado Propietario

Como se indica en la especificación de JPA en la sección 2.9, es una buena práctica marcar muchos a uno como el lado propietario.

En otras palabras, los artículos serían el lado propietario y el carro el lado inverso, que es exactamente lo que hicimos antes.

Entonces, ¿cómo logramos esto?

Al incluir el atributo mappedBy en la clase Cart, lo marcamos como el lado inverso.

Al mismo tiempo, también anotamos los elementos.campo de carrito con @ ManyToOne, haciendo que los artículos sean el lado propietario.

Volviendo a nuestro ejemplo de «inconsistencia», ahora Hibernate sabe que la referencia de item2 es más importante y guardará la referencia de item2 a la base de datos.

Comprobemos el resultado:

item1 ID=1, Foreign Key Cart ID=1item2 ID=2, Foreign Key Cart ID=2

Aunque el carrito hace referencia a item2 en nuestro fragmento, la referencia de item2 a cart2 se guarda en la base de datos.

6.3. Carrito como el Lado Propietario

También es posible marcar el lado uno a muchos como el lado propietario y el lado muchos a uno como el lado inverso.

Aunque esta no es una práctica recomendada, vamos a intentarlo.

El fragmento de código a continuación muestra la implementación del lado uno a muchos como el lado propietario:

Observe cómo eliminamos el elemento mappedBy y configuramos la columna de @JoinColumn de muchos a uno como insertable y actualizable a false.

Si ejecutamos el mismo código, el resultado será el contrario:

item1 ID=1, Foreign Key Cart ID=1item2 ID=2, Foreign Key Cart ID=1

Como se muestra arriba, ahora item2 pertenece al carrito.

Conclusión

Hemos visto lo fácil que es implementar la relación uno a muchos con la base de datos Hibernada OR y H2 usando anotaciones JPA.

Además, aprendimos sobre las relaciones bidireccionales y cómo implementar la noción de un lado propietario.