OneToMany: anotaciones

Estas son las anotaciones que debes incorporar a tus entidades si quieres crear una relación OneToMany. Una de ellas deberá llevar la anotación OneToMany, y para crear el recíproco la otra deberá llevar el ManyToOne.

Este curso ha sido marcado como anticuado y no está siendo revisado de forma activa. Es posible que la información pueda estar desactualizada o que los enlaces se hayan roto.

Cuando trabajamos con JPA para modelar relaciones entre entidades, una de las más comunes es la relación One to Many y su inversa Many to One. En este caso, imaginemos que tenemos una entidad Autor y otra entidad Libro, donde un autor puede tener muchos libros, y cada libro pertenece a un único autor.

Para entender bien cómo definir estas relaciones, es importante fijarnos en el significado de los términos One y Many en la anotación. El lado que está a la izquierda, el One, se refiere a la entidad en la que estamos trabajando, en este caso Autor. El Many, a la derecha, hace referencia a la entidad relacionada, que sería Libro. Por lo tanto, la relación One to Many indica que un autor está asociado a muchos libros.

En la entidad Autor, para representar esta relación, usamos la anotación @OneToMany. Aquí debemos indicarle a JPA cuál es el campo en la entidad Libro que referencia al autor. Esto se hace con el atributo mappedBy, que debe contener el nombre del campo en Libro que apunta al autor. Por ejemplo, si en la clase Libro tenemos un campo llamado autor que representa esta relación, entonces en Autor pondremos mappedBy = "autor". Esto le dice a JPA que la relación se mantiene en la tabla de libros, y que la tabla de autores no necesita almacenar información adicional sobre los libros.

Además, podemos configurar el comportamiento en cascada con el atributo cascade. Si queremos que al guardar un autor también se guarden automáticamente sus libros asociados, podemos usar cascade = CascadeType.ALL. Esto facilita la gestión de las entidades relacionadas.

Respecto a la carga de datos, el atributo fetch nos permite controlar cuándo se cargan los datos relacionados. En las relaciones One to Many, el valor por defecto es FetchType.LAZY, lo que significa que los libros asociados a un autor no se cargarán automáticamente al recuperar el autor, sino que se cargarán solo cuando los necesitemos. Esto es útil para optimizar recursos y evitar cargas innecesarias.

Por otro lado, en la entidad Libro, definimos la relación Many to One con la anotación @ManyToOne. Aquí también podemos configurar el cascade y el fetch. En este caso, es recomendable especificar fetch = FetchType.LAZY para que el autor de un libro no se cargue automáticamente hasta que se acceda a él. Aunque pueda parecer extraño que un objeto se cargue de forma perezosa, Hibernate utiliza un proxy que extiende la clase Autor y que solo carga los datos reales cuando se invoca un método, como getAutor().

Finalmente, para que JPA sepa cómo unir las tablas en la base de datos, en la entidad Libro usamos la anotación @JoinColumn. Aquí definimos el nombre de la columna que almacenará la clave foránea del autor, por ejemplo autor_id. Esto indica que en la tabla libros habrá una columna autor_id que referencia al identificador del autor correspondiente.

Un ejemplo simplificado de cómo quedarían las entidades sería el siguiente:

@Entity
public class Autor {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String nombre;

    @OneToMany(mappedBy = "autor", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Libro> libros;

    // getters y setters
}
@Entity
public class Libro {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String titulo;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "autor_id")
    private Autor autor;

    // getters y setters
}

Es importante evitar incluir en los métodos toString() las referencias bidireccionales, ya que esto puede provocar bucles infinitos al imprimir las entidades. Por ejemplo, si en Libro incluimos el autor en el toString() y en Autor incluimos la lista de libros, al imprimir uno se llamará al otro recursivamente.

Con esta configuración, conseguimos que la tabla de autores se mantenga limpia y que la relación se gestione principalmente desde la tabla de libros, optimizando la carga de datos y facilitando la gestión de las entidades relacionadas. En próximas ocasiones podremos probar que todo funciona correctamente y abordar algunos errores comunes que pueden surgir al trabajar con estas relaciones.

Lista de reproducción
  1. 1
    La persistencia es clave
    6 minutos
  2. 2
    Instalando Hibernate
    8 minutos
  3. 3
    Crear el persistence.xml
    9 minutos
  4. 4
    Construyendo una Entity
    8 minutos
  5. 5
    Accediendo al EntityManager
    9 minutos
  6. 6
    Insertando con persist
    7 minutos
  7. 7
    Managed Entities
    6 minutos
  8. 8
    Merge y remove
    5 minutos
  9. 9
    Inciso sobre Java 8
    7 minutos
  10. 10
    Introducción a relaciones
    6 minutos
  11. 11
    Relación OneToOne
    11 minutos
  12. 12
    OneToOne inverso con mappedBy
    8 minutos
  13. 13
    OneToMany: planteamiento
    6 minutos
  14. 14
    OneToMany: anotaciones
    6 minutos
  15. 15
    OneToMany: EntityManager
    7 minutos
  16. 16
    ¡AYUDA! Error Lazy Initialization (OneToMany)
    5 minutos
  17. 17
    ¡AYUDA! No se fijan las relaciones (OneToMany)
    8 minutos
  18. 18
    Borrar hijos en un OneToMany
    11 minutos
  19. 19
    ON DELETE SET NULL
    8 minutos