Топ-100Типы извлечения данных в Hibernate (fetch types) - CodOrbits
LogoCodOrbits

Раздел: Hibernate

Познакомьтесь с Hibernate — ORM-фреймворком Java для удобной работы с базами данных через объекты.

Все разделы
Иконка Hibernate

Типы извлечения данных в Hibernate (fetch types)

Last updated: 11 мая 2025 г.

LAZY, EAGERэто типы извлечения данных.

Подробнее ниже.

1package HibernateApps;
2
3import java.util.List;
4
5import javax.persistence.CascadeType;
6import javax.persistence.Column;
7import javax.persistence.Entity;
8import javax.persistence.FetchType;
9import javax.persistence.GeneratedValue;
10import javax.persistence.GenerationType;
11import javax.persistence.Id;
12import javax.persistence.JoinColumn;
13import javax.persistence.OneToMany;
14import javax.persistence.OneToOne;
15import javax.persistence.Table;
16
17@Entity
18//Этот класс с таблицы author
19@Table(name = "author")
20public class Author {
21    @Id
22    @GeneratedValue(
23            strategy = GenerationType.IDENTITY
24    )
25    private int id;
26
27    @Column(name="name")
28    private String authorName;
29
30    @OneToOne(cascade = {CascadeType.ALL})
31    @JoinColumn(name="author_info_id")
32    private AuthorInfo authorInfo;
33
34    // LAZY, EAGER – это типы извлечения данных.
35    // Если мы извлекаем автора из БД в объект Author
36    // то извлекаются из БД и его authorbooks.
37    // В прошлом уроке мы видели как это работает.
38    // В этом же уроке мы рассмотрим настройку
39    // того КОГДА извлечение книг будет происходить.
40    // При настроеном EAGER книги автора извлекаються
41    // из БД в список authorbooks, который
42    // в объекте Author СРАЗУ как только мы извлекли
43    // в этот объект Author автора из базы,
44    // но очевидно что это плохо может сказаться
45    // на производительности так как что если мы
46    // хотим в конкретной ситуации извлечь
47    // только автора, а связанные с ним строки в других
48    // таблицах, такие как его книги, пока не извлекать
49    // поскольку в этой конкретной ситуации они нам
50    // пока не нужны.
51    // Решение это LAZY. Здесь все просто.
52    // Данные связанных с автором таблиц извлекаются
53    // только тогда когда они нам нужны. То есть при извлечении
54    // автора из базы извлекается только автор,
55    // а связанные с ним книжки нет, они извлекуться
56    // и добавяться в List объекта извлеченного автора
57    // только когда у этого объекта будет вызван
58    // метод getAuthorBooks() либо любой другой метод,
59    // в котором будет использоваться List с книгами.
60    // При OneToMany и ManyToMany по умолчанию
61    // стоит LAZY, при других EAGER.
62
63    //Сначала приведем пример с EAGER.
64    @OneToMany(fetch=FetchType.EAGER,
65                mappedBy="author",
66                cascade = CascadeType.ALL)
67    private List<AuthorBooks> authorbooks;
68
69
70    public Author() {
71    }
72
73    public Author(String authorName) {
74        this.authorName = authorName;
75    }
76
77    public int getId() {
78        return id;
79    }
80
81    public void setId(int id) {
82        this.id = id;
83    }
84
85    public String getAuthorName() {
86        return authorName;
87    }
88
89    public void setAuthorName(
90            String authorName) {
91        this.authorName = authorName;
92    }
93
94    public AuthorInfo getAuthorInfo() {
95        return authorInfo;
96    }
97
98    public void setAuthorInfo(
99            AuthorInfo authorInfo) {
100        this.authorInfo = authorInfo;
101    }
102
103    //добавляем геттер сеттер для списка
104    public List<AuthorBooks> getAuthorBooks(){
105        return authorbooks;
106    }
107
108    public void setAuthorBooks(
109            List<AuthorBooks> authorbooks){
110        this.authorbooks = authorbooks;
111    }
112
113
114    @Override
115    public String toString() {
116        return "Author [id=" + id
117                + ", authorName="
118                + authorName
119                + ", authorInfo="
120                + authorInfo
121                + ", authorbooks="
122                + authorbooks + "]";
123    }
124}

Пример программы с EAGER типом извлечения данных:

1package HibernateApps;
2
3import org.hibernate.Session;
4import org.hibernate.SessionFactory;
5import org.hibernate.cfg.Configuration;
6
7
8public class HibernateApp {
9
10  public static void main(String[] args) {
11
12    SessionFactory sessionFactory =
13        new Configuration()
14        .configure("hibernate.cfg.xml")
15        .addAnnotatedClass(Author.class)
16        .addAnnotatedClass(AuthorInfo.class)
17        .addAnnotatedClass(AuthorBooks.class)
18        .buildSessionFactory();
19
20    Session session = sessionFactory.getCurrentSession();
21
22
23    try {
24
25      session.beginTransaction();
26
27      //Здесь мы выбираем из БД автора
28      //и как говорилось данные связанные
29      //с этим автором в других таблицах
30      //загружаються из БД в обьект author
31      //СРАЗУ поскольку настроено EAGER.
32      Author author = session.get(Author.class,1);
33      //Обьект уже author содержит все книги
34      //связанные с автором.
35      //То есть они извлеклись из БД
36      //СРАЗУ как только мы вызвали get.
37
38
39      session.getTransaction().commit();
40
41    } catch (Exception e) {
42      session.getTransaction().rollback();
43      e.printStackTrace();
44    } finally {
45
46      session.close();
47    }
48
49
50  }
51
52}

Давайте запустим нашу программу.

Как видим, по вызову метода get произошел запрос select, который извлекает не только автора из БД, а и его книги благодаря тому, что тип извлечения книг был установлен в EAGER.


Настройка типа извлечения данных.

Теперь изменим тип извлечения данных на LAZY.

1package HibernateApps;
2
3import java.util.List;
4import javax.persistence.*;
5
6@Entity
7//это класс с таблицы author
8@Table(name = "author")
9public class Author {
10
11    @Id
12    @GeneratedValue(
13            strategy=GenerationType.IDENTITY
14    )
15    @Column(name="id")
16    private int id;
17
18    @Column(name="name")
19    private String authorName;
20
21    @OneToOne(cascade=CascadeType.ALL)
22    @JoinColumn(name="author_info_id")
23    private AuthorInfo authorInfo;
24
25    //Теперь приведем пример с LAZY.
26
27    @OneToMany(fetch=FetchType.LAZY,
28               mappedBy="author",
29               cascade = CascadeType.ALL)
30    private List<AuthorBooks> authorbooks;
31
32    public Author() {
33    }
34
35    public Author(String authorName) {
36        this.authorName = authorName;
37    }
38
39
40    public int getId() {
41        return id;
42    }
43
44    public void setId(int id) {
45        this.id = id;
46    }
47
48    public String getAuthorName() {
49        return authorName;
50    }
51
52    public void setAuthorName(
53            String authorName) {
54        this.authorName = authorName;
55    }
56
57    public AuthorInfo getAuthorInfo() {
58        return authorInfo;
59    }
60
61    public void setAuthorInfo(
62            AuthorInfo authorInfo) {
63        this.authorInfo = authorInfo;
64    }
65
66    //добавляем геттер сеттер для списка
67    public List<AuthorBooks> getAuthorBooks(){
68        return authorbooks;
69    }
70
71    public void setAuthorBooks(
72            List<AuthorBooks> authorbooks){
73        this.authorbooks = authorbooks;
74    }
75
76    @Override
77    public String toString() {
78        return "Author [id=" + id
79                + ", authorName="
80                + authorName
81                + ", authorInfo="
82                + authorInfo
83                + ", authorbooks="
84                + authorbooks + "]";
85    }
86}

Пример программы с LAZY типом извлечения данных:

1package HibernateApp;
2
3import org.hibernate.Session;
4import org.hibernate.SessionFactory;
5import org.hibernate.cfg.Configuration;
6
7public class HibernateApp {
8  public static void main(String[] args) {
9    SessionFactory sessionFactory =
10      new Configuration()
11      .configure("hibernate.cfg.xml")
12      .addAnnotatedClass(AuthorInfo.class)
13      .addAnnotatedClass(AuthorBooks.class)
14      .buildSessionFactory();
15
16    Session session =
17      sessionFactory.getCurrentSession();
18
19    try {
20      session.beginTransaction();
21
22      //Здесь мы выбираем из БД автора
23      //и как говорилось данные связанные
24      //с этим автором в других таблицах
25      //загружаються из БД в объект author
26      //НЕ СРАЗУ при вызове get поскольку
27      //используеться LAZY.
28      Author author=session.get(Author.class,1);
29      //Объект author пока НЕ содержит книги
30      //связанные с извлеченным только
31      //что автором. То есть они ПОКА
32      //не извлеклись из БД.
33
34      //Давайте теперь извлечем книги из БД
35      //в объект вызвав метод, в котором
36      //используеться List, в котором должны
37      //храниться книги автора.
38      author.getAuthorBooks();
39      //Теперь объект автора содержит связанные
40      //с ним в БД книги.
41      session.getTransaction().commit();
42
43    } catch (Exception e) {
44      session.getTransaction().rollback();
45      e.printStackTrace();
46    } finally {
47      session.close();
48    }
49  }
50}

Давайте запустим нашу программу.

Как видим, по вызову метода get произошел запрос select, который не извлекает книги из БД, а только автора (ну на самом деле на скриншоте еще можно увидеть, что он также извлекает и из таблицы author_info из-за того, что по умолчанию у связей OneToOne стоит тип извлечения данных EAGER).

Это поведение стало возможным благодаря тому, что для коллекции книг был установлен тип извлечения LAZY.

Также на скриншоте видно, что произошёл второй запрос. Он был выполнен при вызове метода getAuthorBooks(). Именно тогда был выполнен дополнительный select, который извлёк книги из базы данных и поместил их в список внутри объекта автора.

В конце можно увидеть содержимое этого списка.


Следующие уроки

Настройка связи Многие-ко-Многим в Hibernate приложении

20
мин.

Similar Articles Icon
Divider

Сборщик проектов Maven

17
мин.

Similar Articles Icon
Divider

Создание Maven веб-проекта в Eclipse IDE

16
мин.

Similar Articles Icon