2.1 Параметр fetch

Разработчики Hibernate давно знали о проблеме, связанной с загрузкой дочерних сущностей. Так что первое, что они сделали – это добавили специальный параметр fetch в аннотации @OneToMany, @ManyToMany.

Этот параметр может принимать два значения:

  • EAGER
  • LAZY

Пример:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")

Если параметр fetch равен EAGER, то при загрузке родительской сущности будут загружены и все ее дочерние сущности. Кроме того, Hibernate постарается сделать это одним SQL-запросом, сгенерировав здоровенный запрос и сразу получив все данные.

Если параметр fetch принимает значение LAZY, то при загрузке родительской сущности, дочерняя сущность загружена не будет. Вместо нее будет создан proxy-объект.

С помощью этого proxy-объекта Hibernate будет отслеживать обращение к этой дочерней сущности и при первом обращении загрузит ее в память.

Если вспомнить нашу ситуацию с комментариями:


@Entity
@Table(name="user")
class User {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
   @JoinColumn(name = "user_id")
   public List<Comment> comments;
}

То у тебя есть “шикарный выбор”:

Если fetch = FetchType.EAGER, то Hibernate загрузит все комментарии на 1-й строке кода:


User user = session.get(User.class, 1);		//загрузит все комментарии тут
List<Comment> comments = user.getComments();

Если fetch = FetchType.LAZY, то Hibernate загрузит все комментарии на 2-й строке кода:


User user = session.get(User.class, 1);
List<Comment> comments = user.getComments(); //загрузит все комментарии тут

Как ты уже догадываешься, варианта, когда он не загрузит все комментарии у тебя нет :)

2.2 Значение по умолчанию

Если ты не указал параметр fetch для аннотации @ManyTo…, то Hibernate будет использовать значения по умолчанию.

Они немного отличаются для различных типов аннотаций. Для аннотаций @OneToOne и @ManyToOne – это EAGER, для аннотаций @OneToMany и @ManyToMany – это LAZY. Запомнить просто – если мы ссылаемся на один объект, то он будет загружен полностью. Если ссылаемся на коллекцию, то она будет загружена при первом обращении к ней.

2.3 Аннотация @LazyCollection

Как ты уже убедился, параметр fetch не сильно помогает при работе с коллекциями. Создатели Hibernate попробовали это исправить, добавив специальную аннотацию @LazyCollection. Пишется она обычно так:

@LazyCollection(LazyCollectionOption.TRUE)

Указывать ее нужно при маппинге полей-коллекций:


@Entity
@Table(name="user")
class User {
   @Column(name="id")
   public Integer id;
 
   @OneToMany(cascade = CascadeType.ALL)
   @LazyCollection(LazyCollectionOption.TRUE)
   public List<Comment> comments;
}

Эта аннотация имеет параметр value, который может принимать одно из трех значений:

  • LazyCollectionOption.TRUE
  • LazyCollectionOption.FALSE
  • LazyCollectionOption.EXTRA

Первые два варианта очень похожи на параметр fetch.

Если параметр установлен в LazyCollectionOption.TRUE, то это значит, что значения поля comments не будут загружены из базы в момент загрузки родительского объекта User. Объекты типа Comment будут загружены при первом обращении к полю comments. Фактически это эквивалент параметра FetchType.LAZY

Если параметр установлен в LazyCollectionOption.FALSE, то это значит, что значения поля comments будут загружены из базы в момент загрузки родительского объекта User. Объекты типа Comment будут загружены при первом обращении к полю comments. Фактически это эквивалент параметра FetchType.EAGER.

undefined
1
Задача
Модуль 4. Работа с БД, 14 уровень, 1 лекция
Недоступна
task1401
Есть три класса-энтити: Author, Book и Publisher. У Author и Publisher не хватает аннотаций на полях books...
undefined
1
Задача
Модуль 4. Работа с БД, 14 уровень, 1 лекция
Недоступна
task1402
Есть три класса-энтити: Author, Book и Publisher. У Author и Publisher замени параметр fetch аннотации...