Hibernate

Hibernate

Tutorial Hibernate: Optimización de asociaciones con carga lazy

Hibernate lazy: carga diferida. Aprende a implementar la carga diferida en Hibernate con ejemplos prácticos y detallados.

Introducción

La optimización de asociaciones con carga lazy en Hibernate es una práctica común para mejorar el rendimiento de las consultas a la base de datos al cargar entidades relacionadas solo cuando sea necesario. 

La carga perezosa (lazy loading) retrasa la recuperación de datos relacionados hasta el momento en que realmente se necesitan, lo que puede reducir la sobrecarga de la base de datos y mejorar el rendimiento de la aplicación.

FetchType.LAZY

Considera un ejemplo de una relación many-to-one entre dos entidades: Book y Author

Cada libro está asociado a un único autor. En este caso, podríamos querer cargar los detalles del autor solo cuando sea necesario, en lugar de cargarlos automáticamente cada vez que recuperamos un libro de la base de datos.

Primero, definimos nuestras entidades Book y Author con la anotación @ManyToOne en la entidad Book para representar la relación con Author. Luego, configuramos la carga perezosa en la asociación usando la anotación @ManyToOne(fetch = FetchType.LAZY).

package com.example.model;

import jakarta.persistence.*;

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToOne(fetch = FetchType.LAZY) // Por defecto es EAGER
    private Author author;

    // Getters and setters
}
package com.example.model;

import jakarta.persistence.*;

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    // Getters and setters
}

En este ejemplo, la asociación entre Book y Author se carga perezosamente, lo que significa que cuando recuperamos un objeto Book de la base de datos, el objeto Author asociado no se cargará automáticamente

En cambio, Hibernate generará una consulta separada para cargar los detalles del autor solo cuando se acceda explícitamente a la propiedad author de un objeto Book.

package com.example.service;

import com.example.model.Book;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class BookService {
    @PersistenceContext
    private EntityManager entityManager;

    public Book findBookById(Long id) {
        return entityManager.find(Book.class, id);
    }
}

En el servicio BookService, cuando recuperamos un libro por su identificador utilizando el método findBookById, Hibernate solo recuperará los detalles del libro y no cargará automáticamente el autor asociado. 

Sin embargo, si posteriormente accedemos a la propiedad author del libro recuperado, Hibernate generará una consulta adicional para cargar los detalles del autor.

Book book = bookService.findBookById(1L);
// Hasta este punto, solo se ha cargado el libro, no el autor.

Author author = book.getAuthor(); // Hibernate generará una consulta para cargar el autor.

Esto permite que la carga de datos se optimice para minimizar la sobrecarga en la base de datos y mejorar el rendimiento de la aplicación, ya que solo se recuperan los datos relacionados cuando realmente se necesitan.

El FetchType.LAZY puede aplicarse a todos los tipos de asociaciones en Hibernate, incluyendo @OneToOne, @OneToMany, @ManyToOne, y @ManyToMany.

Atributos básicos

Los atributos básicos también pueden configurarse para cargarse de manera perezosa utilizando la anotación @Basic con un modo de carga lazy. Esto es útil para atributos grandes que no se necesitan siempre, como blobs o textos largos.

import jakarta.persistence.*;

@Entity
public class Document {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Basic(fetch = FetchType.LAZY)
    private byte[] fileContent;

    // Getters and setters
}

La anotación @Basic(fetch = FetchType.LAZY) indica que el contenido del archivo representado por byte[] fileContent no se cargará automáticamente cuando la entidad a la que pertenece sea recuperada de la base de datos. En cambio, fileContent solo se cargará en la memoria cuando el código acceda específicamente a este campo.

@LazyCollection

Hibernate también ofrece la anotación @LazyCollection que puede ser usada en colecciones para especificar explícitamente la estrategia de carga lazy, independientemente de las configuraciones globales.

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import jakarta.persistence.*;

@Entity
public class Author {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "author")
    @LazyCollection(LazyCollectionOption.TRUE)
    private Set<Book> books;

    // Getters and setters
}

La anotación @OneToMany(mappedBy = "author") establece una relación de uno a muchos entre Author y Book, indicando que un autor puede tener múltiples libros. 

Sin embargo, la adición de @LazyCollection(LazyCollectionOption.TRUE) modifica el comportamiento de carga predeterminado de esta colección. En lugar de cargar todos los libros asociados a un autor tan pronto como se recupera el autor de la base de datos (comportamiento de carga eager por defecto en algunas configuraciones de @OneToMany), la opción LazyCollectionOption.TRUE asegura que los libros solo se cargarán cuando se acceda explícitamente a la colección books.

La distinción entre usar @OneToMany(fetch = FetchType.LAZY) y @LazyCollection(LazyCollectionOption.TRUE) en Hibernate se centra en cómo gestionan la carga perezosa de colecciones. @OneToMany(fetch = FetchType.LAZY) es una parte estándar de JPA que utiliza proxies para diferir la carga de las colecciones hasta que son accedidas, ofreciendo así compatibilidad entre diferentes implementaciones de JPA. 

Por otro lado, @LazyCollection(LazyCollectionOption.TRUE) es exclusivo de Hibernate y proporciona un control más preciso sobre la carga de colecciones, evitando en algunos casos el uso de proxies, lo que resulta útil en situaciones donde los proxies presentan limitaciones o complicaciones. 

Básicamente, ambas permiten carga lazy, pero mientras @OneToMany con FetchType.LAZY asegura la portabilidad, @LazyCollection ofrece opciones más específicas y adaptadas para optimizar el rendimiento dentro del ecosistema de Hibernate.

Certifícate en Hibernate con CertiDevs PLUS

Ejercicios de esta lección Optimización de asociaciones con carga lazy

Evalúa tus conocimientos de esta lección Optimización de asociaciones con carga lazy con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Consultas JPQL avanzadas

Hibernate
Código

Configuración con JPA

Hibernate
Test

Tipos de datos personalizados

Hibernate
Puzzle

Consultas Criteria avanzadas

Hibernate
Código

Operaciones en cascada

Hibernate
Test

Anotaciones JPA

Hibernate
Puzzle

Asociación Many To One

Hibernate
Test

Funciones en consultas JPQL

Hibernate
Código

Asociación Many To Many entre Actor y Pelicula

Hibernate
Código

Asociación One To Many entre Curso y Estudiante

Hibernate
Código

Tipos de datos básicos

Hibernate
Test

Consultas Criteria básicas

Hibernate
Código

Asociación Many To Many

Hibernate
Puzzle

CRUD de entidades con asociaciones

Hibernate
Proyecto

Optimización de asociaciones con carga lazy

Hibernate
Código

Asociación One To Many

Hibernate
Puzzle

Configuración con Maven

Hibernate
Test

Asociación One To One

Hibernate
Test

CRUD en Hibernate

Hibernate
Código

Operaciones en cascada

Hibernate
Puzzle

Introducción a Hibernate

Hibernate
Test

Atributos de tipo enum en entidades JPA

Hibernate
Código

Carga de asociaciones en consultas con EntityGraph

Hibernate
Código

Configuración con Gradle

Hibernate
Test

Asociación One To One entre Libro y Resumen

Hibernate
Código

Asociación One To Many

Hibernate
Test

Asociación Many To Many

Hibernate
Test

Creación de entidades

Hibernate
Test

Ciclo de vida de una entidad

Hibernate
Código

Consultas JPQL básicas

Hibernate
Código

Carga de asociaciones en consultas con EntityGraph y anotaciones

Hibernate
Código

Tipos de datos embebidos

Hibernate
Código

Asociación Many To One entre Paciente y Clinica

Hibernate
Código

Asociación Many To One

Hibernate
Puzzle

Optimización de consultas con DTOs

Hibernate
Código

Atributos @Transient en entidades

Hibernate
Código

Asociación One To One

Hibernate
Puzzle

Todas las lecciones de Hibernate

Accede a todas las lecciones de Hibernate y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Hibernate

Hibernate

Introducción Y Entorno

Configuración Hibernate Con Gradle

Hibernate

Introducción Y Entorno

Configuración Hibernate Con Maven

Hibernate

Introducción Y Entorno

Configuración Hibernate Con Jpa

Hibernate

Introducción Y Entorno

Creación De Entidades Jpa

Hibernate

Entidades Jpa Y Tipos De Datos

Tipos De Datos En Hibernate

Hibernate

Entidades Jpa Y Tipos De Datos

Atributos @Transient En Entidades

Hibernate

Entidades Jpa Y Tipos De Datos

Enums En Hibernate

Hibernate

Entidades Jpa Y Tipos De Datos

Tipos De Datos Embebidos

Hibernate

Entidades Jpa Y Tipos De Datos

Crud En Hibernate

Hibernate

Entidades Jpa Y Tipos De Datos

Ciclo De Vida De Una Entidad

Hibernate

Entidades Jpa Y Tipos De Datos

Asociación One To One

Hibernate

Asociaciones Entre Entidades

Asociación One To Many

Hibernate

Asociaciones Entre Entidades

Asociación Many To One

Hibernate

Asociaciones Entre Entidades

Asociación Many To Many

Hibernate

Asociaciones Entre Entidades

Operaciones En Cascada

Hibernate

Asociaciones Entre Entidades

Consultas Jpql Básicas

Hibernate

Consultas Hql Y Jpql

Consultas Jpql Avanzadas

Hibernate

Consultas Hql Y Jpql

Funciones En Consultas Jpql

Hibernate

Consultas Hql Y Jpql

Consultas Criteria Básicas

Hibernate

Api Criteria De Jpa

Consultas Criteria Avanzadas

Hibernate

Api Criteria De Jpa

Carga De Asociaciones En Consultas Con Entitygraph

Hibernate

Api Entitygraph

Carga De Asociaciones En Consultas Con Entitygraph Y Anotaciones

Hibernate

Api Entitygraph

Optimización De Consultas Con Dtos

Hibernate

Optimización

Optimización De Asociaciones Con Carga Lazy

Hibernate

Optimización

Certificados de superación de Hibernate

Supera todos los ejercicios de programación del curso de Hibernate y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender el concepto de carga lazy y su impacto en el rendimiento de las aplicaciones.
  2. Aprender a implementar carga lazy en relaciones y para atributos básicos utilizando anotaciones específicas en Hibernate.
  3. Entender el uso de @LazyCollection para especificar la estrategia de carga lazy en colecciones.