Buscar..


Lazy Loading vs Eager Loading

La obtención o carga de datos se puede clasificar principalmente en dos tipos: ansiosos y perezosos.

Para utilizar Hibernate, asegúrese de agregar la última versión a la sección de dependencias de su archivo pom.xml:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>   
    <version>5.2.1.Final</version>
</dependency>

1. Carga impaciente y carga perezosa

Lo primero que debemos discutir aquí es qué carga perezosa y carga ansiosa son:

Eager Loading es un patrón de diseño en el que la inicialización de datos se produce en el lugar. Esto significa que las colecciones se recuperan por completo en el momento en que se recuperan los padres (se recupera inmediatamente)

La carga perezosa es un patrón de diseño que se utiliza para diferir la inicialización de un objeto hasta el punto en el que se necesita. Esto puede contribuir efectivamente al rendimiento de la aplicación.

2. Usando los diferentes tipos de carga

La carga diferida se puede habilitar usando el siguiente parámetro XML:

lazy="true"

Vamos a profundizar en el ejemplo. Primero tenemos una clase de usuario:

public class User implements Serializable {
   
    private Long userId;
    private String userName;
    private String firstName;
    private String lastName;
    private Set<OrderDetail> orderDetail = new HashSet<>();

    //setters and getters
    //equals and hashcode
    }

Mira el Set de orderDetail que tenemos. Ahora echemos un vistazo a la clase OrderDetail :

public class OrderDetail implements Serializable {

    private Long orderId;
    private Date orderDate;
    private String orderDesc;
    private User user;

    //setters and getters
    //equals and hashcode
}

La parte importante que interviene en la configuración de la carga diferida en el UserLazy.hbm.xml :

<set name="orderDetail" table="USER_ORDER" inverse="true" lazy="true" fetch="select">
    <key>
        <column name="USER_ID" not-null="true" />
    </key>
   <one-to-many class="com.baeldung.hibernate.fetching.model.OrderDetail" />
</set>

Así es como se habilita la carga lenta. Para deshabilitar la carga perezosa, simplemente podemos usar: lazy = "false" y esto a su vez habilitará la carga impaciente. El siguiente es el ejemplo de configurar una carga impaciente en otro archivo User.hbm.xml:

<set name="orderDetail" table="USER_ORDER" inverse="true" lazy="false" fetch="select">
    <key>
        <column name="USER_ID" not-null="true" />
    </key>
   <one-to-many class="com.baeldung.hibernate.fetching.model.OrderDetail" />
</set>

Alcance

Para aquellos que no han jugado con estos dos diseños, el alcance de los perezosos y ávidos está dentro de una sesión específica de SessionFactory . Eager carga todo al instante, lo que significa que no hay necesidad de llamar a nada para obtenerlo. Pero la recuperación perezosa suele exigir alguna acción para recuperar la colección / objeto asignado. A veces, esto es problemático, ya que la recuperación fuera de la sesión es lenta . Por ejemplo, tiene una vista que muestra los detalles de algunos POJO asignados.

@Entity
public class User {
    private int userId;
    private String username;
    @OneToMany
    private Set<Page> likedPage;

    // getters and setters here
}

@Entity
public class Page{
    private int pageId;
    private String pageURL;

    // getters and setters here
}

public class LazzyTest{
    public static void main(String...s){
        SessionFactory sessionFactory = new SessionFactory();
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        
        User user = session.get(User.class, 1);
        transaction.commit();
        session.close();
        
        // here comes the lazy fetch issue
        user.getLikedPage();
    }
}

Cuando intente obtener perezosos fuera de la sesión , obtendrá la lazyinitializeException . Esto se debe a que, por defecto, la estrategia de búsqueda para todos los oneToMany o cualquier otra relación es perezosa (llamar a DB a pedido) y cuando se cierra la sesión, no tiene poder para comunicarse con la base de datos. por lo tanto, nuestro código intenta obtener una colección de likedPage y genera una excepción porque no hay una sesión asociada para la representación de la base de datos.

La solución para esto es usar:

  1. Abrir sesión en vista : en la que mantiene la sesión abierta incluso en la vista renderizada.
  2. Hibernate.initialize(user.getLikedPage()) antes de cerrar la sesión: esto le indica a Hibernate que inicialice los elementos de la colección.


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow