Бесплатный курс по Java: от основ до продвинутого уровня
Типы извлечения данных в Hibernate (fetch types)
LAZY, EAGER – это типы извлечения данных.
Подробнее ниже.
package HibernateApps;
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.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
//Этот класс с таблицы author
@Table(name = “author”)
public class Author {
@Id
@GeneratedValue(
strategy = GenerationType.IDENTITY
)
private int id;
@Column(name=”name”)
private String authorName;
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name=”author_info_id”)
private AuthorInfo authorInfo;
// LAZY, EAGER – это типы извлечения данных.
// Если мы извлекаем автора из БД в объект Author
// то извлекаются из БД и его authorbooks.
// В прошлом уроке мы видели как это работает.
// В этом же уроке мы рассмотрим настройку
// того КОГДА извлечение книг будет происходить.
// При настроеном EAGER книги автора извлекаються
// из БД в список authorbooks, который
// в объекте Author СРАЗУ как только мы извлекли
// в этот объект Author автора из базы,
// но очевидно что это плохо может сказаться
// на производительности так как что если мы
// хотим в конкретной ситуации извлечь
// только автора, а связанные с ним строки в других
// таблицах, такие как его книги, пока не извлекать
// поскольку в этой конкретной ситуации они нам
// пока не нужны.
// Решение это LAZY. Здесь все просто.
// Данные связанных с автором таблиц извлекаются
// только тогда когда они нам нужны. То есть при извлечении
// автора из базы извлекается только автор,
// а связанные с ним книжки нет, они извлекуться
// и добавяться в List объекта извлеченного автора
// только когда у этого объекта будет вызван
// метод getAuthorBooks() либо любой другой метод,
// в котором будет использоваться List с книгами.
// При OneToMany и ManyToMany по умолчанию
// стоит LAZY, при других EAGER.
//Сначала приведем пример с EAGER.
@OneToMany(fetch=FetchType.EAGER,
mappedBy=”author”,
cascade = CascadeType.ALL)
private List authorbooks;
public Author() {
}
public Author(String authorName) {
this.authorName = authorName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(
String authorName) {
this.authorName = authorName;
}
public AuthorInfo getAuthorInfo() {
return authorInfo;
}
public void setAuthorInfo(
AuthorInfo authorInfo) {
this.authorInfo = authorInfo;
}
//добавляем геттер сеттер для списка
public List getAuthorBooks(){
return authorbooks;
}
public void setAuthorBooks(
List authorbooks){
this.authorbooks = authorbooks;
}
@Override
public String toString() {
return “Author [id=” + id
+ “, authorName=”
+ authorName
+ “, authorInfo=”
+ authorInfo
+ “, authorbooks=”
+ authorbooks + “]”;
}
}
Пример программы с EAGER типом извлечения данных:
package HibernateApps;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateApp {
public static void main(String[] args) {
SessionFactory sessionFactory =
new Configuration()
.configure(“hibernate.cfg.xml”)
.addAnnotatedClass(Author.class)
.addAnnotatedClass(AuthorInfo.class)
.addAnnotatedClass(AuthorBooks.class)
.buildSessionFactory();
Session session = sessionFactory.getCurrentSession();
try {
session.beginTransaction();
//Здесь мы выбираем из БД автора
//и как говорилось данные связанные
//с этим автором в других таблицах
//загружаються из БД в обьект author
//СРАЗУ поскольку настроено EAGER.
Author author = session.get(Author.class,1);
//Обьект уже author содержит все книги
//связанные с автором.
//То есть они извлеклись из БД
//СРАЗУ как только мы вызвали get.
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
Давайте запустим нашу программу.
Как видим, по вызову метода getпроизошел запрос select, который извлекает не только автора из БД, а и его книги благодаря тому, что тип извлечения книг был установлен в EAGER.
Настройка типа извлечения данных.
Теперь изменим тип извлечения данных на LAZY.
package HibernateApps;
import java.util.List;
import javax.persistence.*;
@Entity
//это класс с таблицы author
@Table(name = “author”)
public class Author {
@Id
@GeneratedValue(
strategy=GenerationType.IDENTITY
)
@Column(name=”id”)
private int id;
@Column(name=”name”)
private String authorName;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name=”author_info_id”)
private AuthorInfo authorInfo;
//Теперь приведем пример с LAZY.
@OneToMany(fetch=FetchType.LAZY,
mappedBy=”author”,
cascade = CascadeType.ALL)
private List authorbooks;
public Author() {
}
public Author(String authorName) {
this.authorName = authorName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(
String authorName) {
this.authorName = authorName;
}
public AuthorInfo getAuthorInfo() {
return authorInfo;
}
public void setAuthorInfo(
AuthorInfo authorInfo) {
this.authorInfo = authorInfo;
}
//добавляем геттер сеттер для списка
public List getAuthorBooks(){
return authorbooks;
}
public void setAuthorBooks(
List authorbooks){
this.authorbooks = authorbooks;
}
@Override
public String toString() {
return “Author [id=” + id
+ “, authorName=”
+ authorName
+ “, authorInfo=”
+ authorInfo
+ “, authorbooks=”
+ authorbooks + “]”;
}
}
Пример программы с LAZY типом извлечения данных:
package HibernateApp;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateApp {
public static void main(String[] args) {
SessionFactory sessionFactory =
new Configuration()
.configure(“hibernate.cfg.xml”)
.addAnnotatedClass(AuthorInfo.class)
.addAnnotatedClass(AuthorBooks.class)
.buildSessionFactory();
Session session =
sessionFactory.getCurrentSession();
try {
session.beginTransaction();
//Здесь мы выбираем из БД автора
//и как говорилось данные связанные
//с этим автором в других таблицах
//загружаються из БД в объект author
//НЕ СРАЗУ при вызове get поскольку
//используеться LAZY.
Author author=session.get(Author.class,1);
//Объект author пока НЕ содержит книги
//связанные с извлеченным только
//что автором. То есть они ПОКА
//не извлеклись из БД.
//Давайте теперь извлечем книги из БД
//в объект вызвав метод, в котором
//используеться List, в котором должны
//храниться книги автора.
author.getAuthorBooks();
//Теперь объект автора содержит связанные
//с ним в БД книги.
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
Давайте запустим нашу программу.
Как видим, по вызову метода getпроизошел запрос select, который не извлекает книги из БД, а только автора (ну на самом деле на скриншоте еще можно увидеть, что он также извлекает и из таблицы author_info из-за того, что по умолчанию у связей OneToOne стоит тип извлечения данных EAGER).
Это поведение стало возможным благодаря тому, что для коллекции книг был установлен тип извлечения LAZY.
Также на скриншоте видно, что произошёл второй запрос. Он был выполнен при вызове метода getAuthorBooks(). Именно тогда был выполнен дополнительный select, который извлёк книги из базы данных и поместил их в список внутри объекта автора.