Cuando trabajamos con JPA para modelar relaciones entre entidades, la anotación @OneToOne nos permite establecer asociaciones uno a uno, donde una instancia de una entidad se vincula con una única instancia de otra. Por ejemplo, un empleado puede tener asignada una única dirección. Sin embargo, si solo definimos esta relación en una dirección, como de empleado a dirección, estamos creando una relación unidireccional: podemos acceder desde el empleado a su dirección, pero no al revés.
Para lograr una relación bidireccional, es decir, que podamos navegar desde la dirección hacia el empleado al que pertenece, debemos añadir un campo en la entidad dirección que apunte al empleado. Esto implica que en la clase Direccion definamos un atributo de tipo Empleado y lo anotemos con @OneToOne. Pero aquí surge un concepto fundamental en JPA y en los ORM en general: el dueño de la relación.
En una relación bidireccional, solo una de las entidades es la propietaria o dueña de la relación. Esta entidad es la que mantiene la clave foránea en la base de datos y controla cómo se persiste la asociación. En nuestro caso, el empleado es el dueño, ya que tiene la columna id_direccion que referencia a la dirección. Por lo tanto, en la entidad dirección debemos indicar que no es el dueño, sino que mapea la relación que ya existe en empleado. Esto se hace con el parámetro mappedBy dentro de la anotación @OneToOne, que debe apuntar al nombre del campo en la entidad dueña, en este caso direccion.
Así, en la clase Direccion tendríamos algo como:
@OneToOne(mappedBy = "direccion", fetch = FetchType.LAZY)
private Empleado empleado;
El uso de mappedBy le dice a JPA que esta relación es la inversa y que no debe crear una columna adicional ni gestionar la clave foránea desde aquí. Además, es recomendable modificar el tipo de carga (fetch) de la relación a LAZY en lugar del valor por defecto EAGER. Esto evita que al cargar una dirección se cargue automáticamente el empleado asociado, lo que puede ser costoso en términos de rendimiento si no siempre necesitamos esa información.
Para ilustrar cómo se almacenan estos datos, podemos observar la base de datos H2 que usamos. En la tabla empleado existe una columna id_direccion que referencia a la clave primaria de la tabla direccion. Por ejemplo, el empleado Pepito Pérez tiene asignada la dirección con id 15, que corresponde a la calle Falso 123 en Springfield. Esto permite realizar consultas SQL con INNER JOIN para obtener datos combinados de empleado y dirección.
Finalmente, al implementar esta relación bidireccional, podemos navegar desde el empleado hacia su dirección con getDireccion(), y desde la dirección hacia el empleado con getEmpleado(). Esto facilita la manipulación de los datos y refleja mejor las asociaciones reales entre las entidades en nuestro modelo de dominio.
Con esta base, estaremos preparados para explorar relaciones más complejas como las one-to-many y many-to-one, que permiten asociar múltiples objetos a una entidad, ampliando las posibilidades de modelado en JPA.