Volver a la página principal
miércoles 11 septiembre 2024
48

Cómo utilizar @OneToMany en Spring Boot

En Spring Boot, la anotación @OneToMany se utiliza para definir una relación de uno a muchos entre dos entidades. Esto significa que una entidad puede estar relacionada con muchas instancias de otra entidad. La relación @OneToMany es común en bases de datos relacionales y permite modelar situaciones como, por ejemplo, una categoría que puede tener múltiples productos asociados.

Ejemplo básico de @OneToMany

Consideremos un ejemplo donde tenemos dos entidades: Usuario y Dirección. Un Usuario puede tener varias Direcciones, lo que implica una relación uno a muchos entre estas dos entidades.

Paso 1: Crear la entidad principal (Usuario)

@Entity
public class Usuario {

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

    private String nombre;

    // Relación OneToMany
    @OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Direccion> direcciones = new ArrayList<>();

    // Getters y Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public List<Direccion> getDirecciones() {
        return direcciones;
    }

    public void setDirecciones(List<Direccion> direcciones) {
        this.direcciones = direcciones;
    }
}
  • @OneToMany(mappedBy = "usuario"): Define la relación uno a muchos. El atributo mappedBy indica que la entidad Direccion tiene una propiedad usuario que será el dueño de la relación.
  • cascade = CascadeType.ALL: Asegura que las operaciones en la entidad Usuario se propaguen a sus Direcciones. Por ejemplo, al eliminar un Usuario, también se eliminarán sus Direcciones.
  • orphanRemoval = true: Permite eliminar direcciones que ya no están asociadas con ningún usuario.

Paso 2: Crear la entidad secundaria (Direccion)

@Entity
public class Direccion {

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

    private String calle;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "usuario_id")
    private Usuario usuario;

    // Getters y Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCalle() {
        return calle;
    }

    public void setCalle(String calle) {
        this.calle = calle;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }
}
  • @ManyToOne: Define el lado inverso de la relación uno a muchos, donde muchas Direcciones están asociadas a un solo Usuario.
  • @JoinColumn(name = "usuario_id"): Especifica la columna en la tabla de Dirección que almacenará la referencia al Usuario.

Paso 3: Persistencia y almacenamiento de datos

Con estas dos entidades, puedes utilizar repositorios de Spring Data JPA para gestionar la persistencia. A continuación, un ejemplo de cómo agregar un usuario con direcciones:

@Service
public class UsuarioService {

    @Autowired
    private UsuarioRepository usuarioRepository;

    public Usuario crearUsuarioConDirecciones() {
        Usuario usuario = new Usuario();
        usuario.setNombre("Juan");

        Direccion direccion1 = new Direccion();
        direccion1.setCalle("Calle 1");
        direccion1.setUsuario(usuario);

        Direccion direccion2 = new Direccion();
        direccion2.setCalle("Calle 2");
        direccion2.setUsuario(usuario);

        usuario.getDirecciones().add(direccion1);
        usuario.getDirecciones().add(direccion2);

        return usuarioRepository.save(usuario);
    }
}

Este código crea un Usuario y dos Direcciones, las cuales son automáticamente asociadas y persistidas en la base de datos debido a la relación @OneToMany.

Paso 4: Repositorios de Spring Data JPA

Debes crear interfaces de repositorio para gestionar las entidades mediante Spring Data JPA:

public interface UsuarioRepository extends JpaRepository<Usuario, Long> {}
public interface DireccionRepository extends JpaRepository<Direccion, Long> {}

Ejemplo completo de consulta

Una vez que los datos se han guardado en la base de datos, puedes consultar los usuarios junto con sus direcciones:

@RestController
@RequestMapping("/usuarios")
public class UsuarioController {

    @Autowired
    private UsuarioRepository usuarioRepository;

    @GetMapping("/{id}")
    public Usuario obtenerUsuario(@PathVariable Long id) {
        return usuarioRepository.findById(id).orElseThrow(() -> new RuntimeException("Usuario no encontrado"));
    }
}

Consideraciones adicionales

  • CascadeType.ALL es útil para propagar operaciones, pero debes usarlo con cuidado, especialmente en sistemas de producción, ya que eliminar un registro padre podría eliminar también los hijos.
  • Lazy loading: El uso de fetch = FetchType.LAZY en @ManyToOne retrasa la carga de la entidad relacionada hasta que se accede explícitamente a ella, lo que mejora el rendimiento.
  • orphanRemoval = true: Si eliminas una dirección del conjunto de direcciones de un usuario y guardas el usuario, esa dirección se eliminará de la base de datos automáticamente.

Conclusión

La anotación @OneToMany en Spring Boot es esencial para modelar relaciones entre entidades de manera eficiente. Te permite manejar relaciones complejas en tus aplicaciones, asegurando la integridad referencial y simplificando la persistencia de datos. Al entender cómo configurar correctamente las entidades y las relaciones, puedes construir aplicaciones robustas y escalables.

Para más detalles, visita la documentación oficial de Spring.

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer