2.1 опция за извличане

Разработчиците на Hibernate знаят за проблема със зареждането на дъщерни обекти от дълго време. Така че първото нещо, което направиха, беше да добавят специален параметър за извличане към анотациите @OneToMany, @ManyToMany.

Този параметър може да приема две стойности:

  • Нетърпелив
  • МЪРЗЕЛИВ

Пример:

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

Ако параметърът за извличане е equals на EAGER , тогава, когато родителският обект се зареди, всички негови дъщерни обекти също ще бъдат заредени. Освен това Hibernate ще се опита да го направи в една SQL заявка, генерирайки масивна заявка и получавайки всички данни наведнъж.

Ако параметърът за извличане приема стойността LAZY , тогава, когато родителският обект е зареден, дъщерният обект няма да бъде зареден. Вместо това ще бъде създаден прокси обект.

С помощта на този прокси обект 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 ще зареди всички коментари на първия ред от codeа:

User user = session.get(User.class, 1);		//load all comments here
List<Comment> comments = user.getComments();

Ако fetch = FetchType.LAZY, тогава Hibernate ще зареди всички коментари на втория ред от codeа:

User user = session.get(User.class, 1);
List<Comment> comments = user.getComments(); //load all comments here

Както вече се досещате, нямате опция, когато не зареди всички коментари :)

2.2 Стойност по подразбиране

Ако не укажете опция за извличане за @ManyToанотацията ..., тогава Hibernate ще използва стойностите по подразбиране.

Те са малко по-различни за различните типове анотации. За анотации @OneToOneи @ManyToOneе НЕПЪЛЕН, за анотации @OneToManyи @ManyToManyе МЪРЗЕЛ. Лесно е да се запомни - ако се позоваваме на един обект, той ще бъде зареден изцяло. Ако се позоваваме на колекция, тогава тя ще бъде заредена при първия достъп до нея.

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;
}

Тази анотация има параметър за стойност, който може да приеме една от трите стойности:

  • LazyCollectionOption. ВЯРНО
  • LazyCollectionOption. НЕВЯРНО
  • LazyCollectionOption. ЕКСТРА

Първите две опции са много подобни на опцията за извличане.

Ако параметърът е зададен на LazyCollectionOption.TRUE, това означава, че стойностите на полето за коментари няма да бъдат заредени от базата данни, когато родителският потребителски обект е зареден. Обекти от тип Коментар ще бъдат заредени при първия достъп до полето за коментари. Всъщност това е еквивалентът на параметъраFetchType.LAZY

Ако параметърът е зададен на LazyCollectionOption.FALSE, това означава, че стойностите на полето за коментари ще бъдат заредени от базата данни в момента на зареждане на родителския потребителски обект. Обекти от тип Коментар ще бъдат заредени при първия достъп до полето за коментари. Всъщност това е еквивалентът на FetchType.EAGER.