Szukaj…


Leniwe ładowanie kontra chętne ładowanie

Pobieranie lub ładowanie danych można przede wszystkim podzielić na dwa typy: chętny i leniwy.

Aby użyć Hibernacji, upewnij się, że dodałeś jego najnowszą wersję do sekcji zależności pliku pom.xml:

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

1. Chętne ładowanie i leniwe ładowanie

Pierwszą rzeczą, o której powinniśmy tutaj porozmawiać, są leniwe ładowanie i chętne ładowanie:

Chętne ładowanie jest wzorcem projektowym, w którym inicjalizacja danych następuje natychmiast. Oznacza to, że kolekcje są pobierane w całości w momencie pobierania ich rodzica (pobieranie natychmiast)

Leniwe ładowanie to wzorzec projektowy, który służy do odroczenia inicjalizacji obiektu do momentu, w którym jest potrzebny. Może to skutecznie przyczynić się do wydajności aplikacji.

2. Korzystanie z różnych rodzajów ładowania

Leniwe ładowanie można włączyć za pomocą następującego parametru XML:

lazy="true"

Przejdźmy do przykładu. Najpierw mamy klasę użytkownika:

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
    }

Spójrz na zestaw szczegółów, który mamy. Teraz spójrzmy na klasę OrderDetail :

public class OrderDetail implements Serializable {

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

    //setters and getters
    //equals and hashcode
}

Ważna część, która jest zaangażowana w ustawienie leniwego ładowania w 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>

W ten sposób włącza się leniwe ładowanie. Aby wyłączyć leniwe ładowanie, możemy po prostu użyć: lazy = "false" a to z kolei umożliwi szybkie ładowanie. Oto przykład konfiguracji szybkiego ładowania w innym pliku 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>

Zakres

Dla tych, którzy nie bawili się tymi dwoma projektami, zakres leniwości i entuzjazmu mieści się w konkretnej sesji SessionFactory . Chętnie ładuje wszystko natychmiast, co oznacza, że nie trzeba dzwonić do niczego, aby je pobrać. Ale opóźnione pobieranie zwykle wymaga pewnych działań w celu odzyskania zmapowanej kolekcji / obiektu. Czasami jest to problematyczne, gdy leniwe pobieranie odbywa się poza sesją . Na przykład masz widok, który pokazuje szczegóły niektórych mapowanych POJO.

@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();
    }
}

Kiedy staramy się leniwy idące poza sesją dostaniesz lazyinitializeException . Wynika to z faktu, że domyślnie strategia pobierania dla wszystkich relacji oneToMany lub innych jest leniwa (połączenie z DB na żądanie), a po zamknięciu sesji nie ma możliwości komunikacji z bazą danych. więc nasz kod próbuje pobrać kolekcję polubionych stron i zgłasza wyjątek, ponieważ nie ma powiązanej sesji do renderowania bazy danych.

Rozwiązaniem tego jest użycie:

  1. Otwórz sesję w widoku - w której sesja jest otwarta nawet w renderowanym widoku.
  2. Hibernate.initialize(user.getLikedPage()) przed zamknięciem sesji - informuje hibernację o zainicjowaniu elementów kolekcji


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow