Разница между FetchType LAZY и EAGER в Java Persistence API? - PullRequest
477 голосов
/ 07 июня 2010

Я новичок в Java Persistence API и Hibernate.

В чем разница между FetchType.LAZY и FetchType.EAGER в Java Persistence API?

Ответы [ 14 ]

919 голосов
/ 07 июня 2010

Иногда у вас есть две сущности, и между ними есть отношения. Например, у вас может быть сущность с именем University и другая сущность с именем Student.

Университетский объект может иметь некоторые базовые свойства, такие как идентификатор, имя, адрес и т. Д., А также свойство, называемое студенты:

public class University {
 private String id;
 private String name;
 private String address;
 private List<Student> students;

 // setters and getters
}

Теперь, когда вы загружаете университет из базы данных, JPA загружает его поля id, name и address для вас. Но у вас есть два варианта для студентов: загрузить его вместе с остальными полями (то есть с нетерпением) или загрузить его по требованию (то есть, лениво), когда вы вызываете университетский метод getStudents ().

Когда в университете много студентов, неэффективно загружать его всеми студентами, когда они не нужны. Таким образом, в подобных случаях вы можете заявить, что хотите, чтобы студенты загружались, когда они действительно необходимы. Это называется отложенной загрузкой.

252 голосов
/ 07 июня 2010

В основном,

LAZY = fetch when needed
EAGER = fetch immediately
62 голосов
/ 07 июня 2010

EAGER загрузка коллекций означает, что они извлекаются полностью во время выборки их родителей. Таким образом, если у вас есть Course, а у него List<Student>, все учащиеся извлекаются из базы данных в момент получения Course.

LAZY, с другой стороны, означает, что содержимое List выбирается только при попытке доступа к ним. Например, позвонив по номеру course.getStudents().iterator(). Вызов любого метода доступа на List инициирует вызов базы данных для извлечения элементов. Это реализуется путем создания прокси вокруг List (или Set). Так что для ваших ленивых коллекций, конкретные типы не ArrayList и HashSet, но PersistentSet и PersistentList (или PersistentBag)

14 голосов
/ 29 января 2013

Я могу рассмотреть производительность и использование памяти. Одно большое отличие состоит в том, что стратегия извлечения EAGER позволяет использовать извлеченный объект данных без сеанса. Почему?
Все данные извлекаются, когда стремятся отметить данные в объекте, когда сеанс подключен. Однако в случае стратегии отложенной загрузки помеченный объект с отложенной загрузкой не извлекает данные, если сеанс отключен (после оператора session.close()). Все это можно сделать с помощью Hibernate-прокси. Стремительная стратегия позволяет данным оставаться доступными после закрытия сессии.

11 голосов
/ 22 июля 2013

По умолчанию для всех объектов коллекции и карты правило выборки равно FetchType.LAZY, а для других экземпляров оно соответствует политике FetchType.EAGER.
Вкратце, отношения @OneToMany и @ManyToMany не извлекают связанные объекты (сбор и отображение) неявным образом, но операция поиска каскадно проходит через поля в @OneToOne и @ManyToOne объектах.

(предоставлено - objectdbcom)

10 голосов
/ 11 марта 2014

Насколько мне известно, оба типа выборки зависят от ваших требований.

FetchType.LAZY по требованию (т. Е. Когда нам потребовались данные).

FetchType.EAGER немедленно (т. Е. Донаше требование приходит, мы без необходимости извлекаем запись)

9 голосов
/ 09 ноября 2014

И FetchType.LAZY, и FetchType.EAGER используются для определения плана выборки по умолчанию .

К сожалению, вы можете переопределить план выборки по умолчанию только для LAZY. Извлечение EAGER менее гибкое и может привести ко многим проблемам с производительностью .

Мой совет - сдерживать стремление к тому, чтобы ваши ассоциации были EAGER, потому что выборка является обязанностью времени запроса. Поэтому все ваши запросы должны использовать директиву fetch , чтобы получать только то, что необходимо для текущего бизнес-кейса.

6 голосов
/ 07 июня 2010

Из Javadoc :

Стратегия EAGER - это требование времени выполнения провайдера постоянства, что данные должны извлекаться с нетерпением.Стратегия LAZY - это подсказка среде выполнения персистентного поставщика о том, что данные должны извлекаться лениво при первом обращении к ним.

Например, нетерпеливый более активен, чем ленивый.Ленивый случается только при первом использовании (если провайдер понимает подсказку), тогда как с нетерпением (возможно) он выбирается заранее.

4 голосов
/ 14 мая 2017

Тип выборки Lazy по умолчанию выбирается Hibernate, если вы не пометите явно Eager Тип выборки.Чтобы быть более точным и кратким, разницу можно указать, как показано ниже.

FetchType.LAZY = Это не загружает отношения, если вы не вызываете их через метод получения.

FetchType.EAGER = Это загружает все отношения.

Плюсы и минусы этих двух типов выборки.

Lazy initialization повышает производительность, избегая ненужных вычислений и сокращая требования к памяти.

Eager initialization занимает больше памяти и скорость обработки низкая.

Сказав, что зависит от ситуации , можно использовать любую из этих инициализаций.

3 голосов
/ 30 апреля 2016

Book.java

        import java.io.Serializable;
        import javax.persistence.Column;
        import javax.persistence.Entity;
        import javax.persistence.GeneratedValue;
        import javax.persistence.GenerationType;
        import javax.persistence.Id;
        import javax.persistence.ManyToOne;
        import javax.persistence.Table;

        @Entity
        @Table(name="Books")
        public class Books implements Serializable{

        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="book_id")
        private int id;
        @Column(name="book_name")
        private String name;

        @Column(name="author_name")
        private String authorName;

        @ManyToOne
        Subject subject;

        public Subject getSubject() {
            return subject;
        }
        public void setSubject(Subject subject) {
            this.subject = subject;
        }

        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAuthorName() {
            return authorName;
        }
        public void setAuthorName(String authorName) {
            this.authorName = authorName;
        }

        }

Subject.java

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue; 
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;

    @Entity
    @Table(name="Subject")
    public class Subject implements Serializable{

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="subject_id")
    private int id;
    @Column(name="subject_name")
    private String name;
    /**
    Observe carefully i have mentioned fetchType.EAGER. By default its is fetchType.LAZY for @OneToMany i have mentioned it but not required. Check the Output by changing it to fetchType.EAGER
    */

    @OneToMany(mappedBy="subject",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)
    List<Books> listBooks=new ArrayList<Books>();

    public List<Books> getListBooks() {
        return listBooks;
    }
    public void setListBooks(List<Books> listBooks) {
        this.listBooks = listBooks;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    }

HibernateUtil.java

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {

 private static SessionFactory sessionFactory ;
 static {
    Configuration configuration = new Configuration();
    configuration.addAnnotatedClass (Com.OneToMany.Books.class);
    configuration.addAnnotatedClass (Com.OneToMany.Subject.class);
    configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
    configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");                                
    configuration.setProperty("hibernate.connection.username", "root");     
    configuration.setProperty("hibernate.connection.password", "root");
    configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
    configuration.setProperty("hibernate.hbm2ddl.auto", "update");
    configuration.setProperty("hibernate.show_sql", "true");
    configuration.setProperty(" hibernate.connection.pool_size", "10");
    configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");
    configuration.setProperty(" hibernate.cache.use_query_cache", "true");
    configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
    configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");

   // configuration
    StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
    sessionFactory = configuration.buildSessionFactory(builder.build());
 }
public static SessionFactory getSessionFactory() {
    return sessionFactory;
}
} 

Main.java

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;

    public class Main {

    public static void main(String[] args) {
        SessionFactory factory=HibernateUtil.getSessionFactory();
        save(factory);
        retrieve(factory);

    }

     private static void retrieve(SessionFactory factory) {
        Session session=factory.openSession();
        try{
            session.getTransaction().begin();
            Subject subject=(Subject)session.get(Subject.class, 1);
            System.out.println("subject associated collection is loading lazily as @OneToMany is lazy loaded");

            Books books=(Books)session.get(Books.class, 1);
            System.out.println("books associated collection is loading eagerly as by default @ManyToOne is Eagerly loaded");
            /*Books b1=(Books)session.get(Books.class, new Integer(1));

            Subject sub=session.get(Subject.class, 1);
            sub.getListBooks().remove(b1);
            session.save(sub);
            session.getTransaction().commit();*/
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            session.close();
        }

        }

       private static void save(SessionFactory factory){
        Subject subject=new Subject();
        subject.setName("C++");

        Books books=new Books();
        books.setAuthorName("Bala");
        books.setName("C++ Book");
        books.setSubject(subject);

        subject.getListBooks().add(books);
        Session session=factory.openSession();
        try{
        session.beginTransaction();

        session.save(subject);

        session.getTransaction().commit();
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            session.close();
        }
    }

    }

Проверьте метод retrieve () файла Main.java. Когда мы получим Subject, его коллекция listBooks , помеченная @OneToMany, будет загружена лениво. Но, с другой стороны, связанное с Книгой объединение коллекции предмет , помеченное @ManyToOne, загружается раньше ([default][1] для @ManyToOne, fetchType=EAGER). Мы можем изменить поведение, поместив fetchType.EAGER в @OneToMany Subject.java или fetchType.LAZY в @ManyToOne в Books.java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...