Asociaciones y Mapeo de Relaciones en Hibernate

  1. Asociación Varios a Uno (Many-to-One)

Consiste en añadir una clave foránea en el extremo "varios" que apunte al extremo "uno". Un caso típico sería múltiples empleados pertenecientes a un mismo departamento.

  1. En la entidad del lado "varios" se incluye una referencia hacia la entidad del lado "uno". Por ejemplo, en Employee se agrega: private Department department;
  2. En el archivo de mapeo Employee.hbm.xml se define la asociación:
<many-to-one name="department" column="deptId"/>

  1. Asociación Uno a Uno por Clave Principal (Unidireccional)

Se logra igualando las claves primarias de ambas entidades, evitando la creación de columnas adicionales. Un ejemplo sería la relación entre una persona y su pasaporte.

  1. La entidad Person mantiene una referencia a Passport:
private Passport passport;

  1. En Person.hbm.xml, la clave principal se configura con la estrategia foreign, indicando que el identificador se obtiene del objeto asociado:
<id name="id">
    <generator class="foreign">
        <param name="property">passport</param>
    </generator>
</id>

  1. Se añade la etiqueta one-to-one con el atributo constrained="true", lo que genera una restricción de clave foránea sobre la clave principal de Person.
<one-to-one name="passport" constrained="true"/>

El atributo constrained indica que la clave principal también actúa como clave foránea hacia Passport. Al persistir un objeto Person, Hibernate guardará también su Passport asociado. Sin embargo, guardar únicamente Passport provocará un error, ya que Passport desconoce la existencia de Person. Este enfoque resulta difícil de mantener.

  1. Asociación Uno a Uno Bidireccional

Permite navegar la relación en ambos sentidos. Por ejemplo, partir de la información de una persona para consultar su pasaporte, y viceversa.

  1. Se añade en Passport una referencia a Person:
private Person person;

  1. En Passport.hbm.xml se incluye la etiqueta correspondiente:
<one-to-one name="person"/>

La etiqueta one-to-one no altera la estructura de la base de datos, solo define cómo se cargan los datos. En cambio, many-to-one sí añade una columna. Es posible controlar el orden de carga mediante el atributo fetch="select".

  1. Asociación Uno a Uno Unidireccional por Clave Foránea Única

Como alternativa al mapeo por clave principal, puede utilizarse una clave foránea con restricción de unicidad. Se trata de un caso particular de varios a uno.

  1. La entidad Person contiene la referencia private Passport passport;, mientras que Passport no conoce a Person.
  2. En Person.hbm.xml se utiliza una estrategia de generación de identificador estándar:
<generator class="native"/>

  1. Se define la asociación mediante many-to-one junto con el atributo unique:
<many-to-one name="passport" unique="true"/>

Es necesario persistir primero el objeto Passport; de lo contrario se lanzará una excepción.

  1. Asociación Uno a Uno Bidireccional por Clave Foránea Única

Se enriquece el mapeo anterior permitiendo la navegación desde ambos extremos.

  1. Se agregan referencias mutuas en ambas entidades.
  2. El mapeo de Person permanece igual. En Passport.hbm.xml se añade:
<one-to-one name="person" property-ref="passport"/>

El atributo property-ref debe indicar el nombre del campo que mantiene la relación en el otro extremo.

  1. Asociación Uno a Varios Unidireccional

El lado "uno" es el encargado de mantener la relación. Se añade una clave foránea en el lado "varios" que apunta al lado "uno". La diferencia respecto a varios a uno radica en qué extremo gestiona la asociación: si lo hace el lado "uno", al cargarlo se recuperan todos los objetos del lado "varios".

Por ejemplo, un departamento puede tener múltiples empleados.

  1. Las entidades Department y Employee poseeen atributos básicos como id y name. En Department se añade:
private Set<Employee> employees;

  1. En Department.hbm.xml se configura la colección:
<set name="employees">
    <key column="deptId"/>
    <one-to-many class="com.example.Employee"/>
</set>

Aunque es posible guardar primero Employee y luego Department, Hibernate emitirá sentencias UPDATE adicionales para mantener la coherencia de la relación.

  1. Asociación Uno a Varios Bidireccional

Se utiliza para resolver las limitaciones del mapeo unidireccional, transfiriendo la responsabilidad de la relación al lado "varios".

  1. Se incorpora en Employee una referencia a Department:
private Department department;

  1. En Employee.hbm.xml se añade:
<many-to-one name="department" column="deptId"/>

  1. En Department.hbm.xml se incluye el atributo inverse="true", cediendo la gestión de la relación a Employee:
<set name="employees" inverse="true">
    <key column="deptId"/>
    <one-to-many class="com.example.Employee"/>
</set>

Se recomienda guardar primero Department y luego Employee. La columna definida en key debe coincidir con la indicada en many-to-one, evitando inconsistencias.

El atributo inverse controla qué extremo mantiene la relación. Su valor por defecto es false; al establecerlo en true, el extremo actual deja de gestionarla y la delega al otro lado. Solo afecta a la persistencia. Por su parte, cascade define la propagación de operaciones entre entidades asociadas.

  1. Asociación Varios a Varios Unidireccional

Un ejemplo sería la relación entre estudiantes y asignaturas. Se requiere una tabla intermedia.

  1. Las entidades Student y Subject contienen atributos básicos. En Student se añade:
private Set<Subject> subjects;

  1. En Student.hbm.xml se define la colección con la tabla de unión:
<set name="subjects" table="student_subject">
    <key column="student_id"/>
    <many-to-many class="com.example.Subject" column="subject_id"/>
</set>

  1. Asociación Varios a Varios Bidireccional

  1. Se añade en Subject la colección inversa:
private Set<Student> students;

  1. En Subject.hbm.xml se configura:
<set name="students" table="student_subject">
    <key column="subject_id"/>
    <many-to-many class="com.example.Student" column="student_id"/>
</set>

Se han cubierto los siete esquemas principales de asociación en Hibernate. La clave para dominar este tema consiste en comprender los diagramas UML correspondientes y, a partir de ahí, ajustar correctamente tanto la clase del modelo como su archivo de configuración.

Etiquetas: Hibernate ORM mapeo-relacional asociaciones HQL

Publicado el 7-30 04:57