Acabo de anunciar el nuevo curso Learn Spring , centrado en los fundamentos de Spring 5 y Spring Boot 2:
>> VER EL CURSO1. Introducción
Cuando se trabaja con un ORM, la búsqueda / carga de datos se puede clasificar en dos tipos: ansiosos y perezosos.
En este artículo rápido, vamos a señalar las diferencias y mostrar que se pueden usar en Hibernate.
2. Dependencias de Maven
Para usar Hibernate, primero definamos la dependencia principal en nuestro pom.xml :
org.hibernate hibernate-core 5.2.2.Final
La última versión de Hibernate se puede encontrar aquí.
3. Carga impaciente y perezosa
Lo primero que deberíamos discutir aquí es qué son la carga diferida y la carga ansiosa:
- La carga ansiosa es un patrón de diseño en el que la inicialización de datos ocurre en el acto
- La carga diferida es un patrón de diseño que se utiliza para diferir la inicialización de un objeto tanto como sea posible
Veamos cómo funciona esto realmente con algunos ejemplos:
La clase UserLazy :
@Entity @Table(name = "USER") public class UserLazy implements Serializable { @Id @GeneratedValue @Column(name = "USER_ID") private Long userId; @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") private Set orderDetail = new HashSet(); // standard setters and getters // also override equals and hashcode }
La clase OrderDetail :
@Entity @Table (name = "USER_ORDER") public class OrderDetail implements Serializable { @Id @GeneratedValue @Column(name="ORDER_ID") private Long orderId; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="USER_ID") private UserLazy user; // standard setters and getters // also override equals and hashcode }
Un usuario puede tener varios OrderDetails . En la estrategia de carga ansiosa, si cargamos los datos del usuario , también cargará todos los pedidos asociados y los almacenará en una memoria .
Pero, cuando la carga diferida está habilitada, si sacamos un UserLazy , los datos de OrderDetail no se inicializarán y cargarán en una memoria hasta que se realice una llamada explícita.
En la siguiente sección veremos cómo se implementa el ejemplo anterior en Hibernate.
4. Configuración de carga
En esta sección veremos cómo podemos configurar las estrategias de búsqueda en Hibernate. Reutilizaremos ejemplos de la sección anterior.
La carga diferida se puede habilitar simplemente usando el siguiente parámetro de anotación:
fetch = FetchType.LAZY
Para usar Eager Fetching se usa el siguiente parámetro:
fetch = FetchType.EAGER
Para configurar Eager Cargando hemos utilizado UserLazy clase hermana 's llamada UserEager .
En la siguiente sección veremos las diferencias entre los dos tipos de recuperación.
5. Diferencias
Como mencionamos, la principal diferencia entre los dos tipos de búsqueda es un momento en el que los datos se cargan en una memoria.
Echemos un vistazo a este ejemplo:
List users = sessionLazy.createQuery("From UserLazy").list(); UserLazy userLazyLoaded = users.get(3); return (userLazyLoaded.getOrderDetail());
Con el enfoque de inicialización diferida, orderDetailSet se inicializará solo cuando se llame explícitamente mediante un getter o algún otro método como se muestra en el ejemplo anterior:
UserLazy userLazyLoaded = users.get(3);
Pero con un enfoque ansioso en UserEager , se inicializará inmediatamente en la primera línea del ejemplo anterior:
List user = sessionEager.createQuery("From UserEager").list();
Para la carga diferida, se utiliza un objeto proxy y se activa una consulta SQL separada para cargar el orderDetailSet .
La idea de deshabilitar los proxies o la carga diferida se considera una mala práctica en Hibernate. Puede resultar en que se obtengan muchos datos de una base de datos y se almacenen en una memoria, independientemente de su necesidad.
El siguiente método se puede utilizar para probar la funcionalidad anterior:
Hibernate.isInitialized(orderDetailSet);
Ahora es importante echar un vistazo a las consultas que se generan en ambos casos:
true
La configuración anterior en fetching.hbm.xml muestra las consultas SQL que se generan. Si observa una salida de consola, podrá ver las consultas generadas.
Para la carga diferida, la consulta que se genera para cargar los datos del usuario :
select user0_.USER_ID as USER_ID1_0_, ... from USER user0_
Sin embargo, en la carga ansiosa, vimos que se hacía una unión con USER_ORDER:
select orderdetai0_.USER_ID as USER_ID4_0_0_, orderdetai0_.ORDER_ID as ORDER_ID1_1_0_, orderdetai0_ ... from USER_ORDER orderdetai0_ where orderdetai0_.USER_ID=?
La consulta anterior se genera para todos los usuarios , lo que da como resultado que se utilice mucha más memoria que en el otro enfoque.
6. Ventajas y desventajas
6.1. Carga lenta
Ventajas:
- El tiempo de carga inicial es mucho menor que en el otro enfoque
- Menor consumo de memoria que en el otro enfoque
Disadvantages:
- Delayed initialization might impact performance during unwanted moments
- In some cases you need to handle lazily-initialized objects with a special care or you might end up with an exception
6.2. Eager Loading:
Advantages:
- No delayed initialization related performance impacts
Disadvantages:
- Long initial loading time
- Loading too much unnecessary data might impact performance
7. Lazy Loading in Hibernate
Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes.
Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity’s class. In our example, when a requested information is missing, it will be loaded from a database before control is ceded to the User class implementation.
También debe tenerse en cuenta que cuando la asociación se representa como una clase de colección (en los ejemplos anteriores se representa como Set orderDetailSet ), se crea un contenedor y se sustituye por una colección original.
Para saber más sobre el patrón de diseño de proxy, puede consultar aquí.
8. Conclusión
En este artículo, mostramos ejemplos de los dos tipos principales de búsqueda que se utilizan en Hibernate.
Para obtener experiencia de nivel avanzado, puede consultar el sitio web oficial de Hibernate. Para obtener el código que se analiza en este artículo, eche un vistazo a este repositorio.
Fondo de persistencia