Нетърпеливо / мързеливо зареждане в хибернация

Устойчивост отгоре

Току що обявих новия курс Learn Spring , фокусиран върху основите на Spring 5 и Spring Boot 2:

>> ПРЕГЛЕД НА КУРСА

1. Въведение

Когато работите с ORM, извличането / зареждането на данни може да бъде класифицирано в два типа: нетърпелив и мързелив.

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

2. Зависимости на Maven

За да използваме Hibernate, нека първо дефинираме основната зависимост в нашия pom.xml :

 org.hibernate hibernate-core 5.2.2.Final 

Най-новата версия на Hibernate можете да намерите тук.

3. Нетърпеливо и мързеливо зареждане

Първото нещо, което трябва да обсъдим тук, е какво представлява мързеливото натоварване и нетърпеливото зареждане:

  • Eager Loading е модел на проектиране, при който инициализирането на данни се извършва на място
  • Мързеливо зареждане е модел на проектиране, който се използва за отлагане на инициализацията на обект, стига да е възможно

Нека да видим как това всъщност работи с някои примери:

В UserLazy класа :

@Entity @Table(name = "USER") public class UserLazy implements Serializable { @Id @GeneratedValue @Column(name = "USER_ID") private Long userId; @OneToMany(fetch = FetchType.LAZY, mappedBy = "user") private Set orderDetail = new HashSet(); // standard setters and getters // also override equals and hashcode }

Класът OrderDetail :

@Entity @Table (name = "USER_ORDER") public class OrderDetail implements Serializable { @Id @GeneratedValue @Column(name="ORDER_ID") private Long orderId; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name="USER_ID") private UserLazy user; // standard setters and getters // also override equals and hashcode }

Един потребител може да има множество OrderDetails . В желаната стратегия за зареждане, ако заредим потребителските данни, тя също ще зареди всички поръчки, свързани с нея, и ще ги съхрани в памет .

Но когато е активирано мързеливо зареждане, ако издърпаме UserLazy , данните от OrderDetail няма да бъдат инициализирани и заредени в памет, докато не бъде направено изрично повикване към тях.

В следващия раздел ще видим как горният пример е реализиран в Hibernate.

4. Зареждане на конфигурация

В този раздел ще разгледаме как можем да конфигурираме стратегии за извличане в хибернация. Ще използваме повторно примери от предишния раздел.

Мързеливо зареждане може просто да бъде активирано, като се използва следният параметър за анотация:

fetch = FetchType.LAZY

За да се използва Eager Fetching се използва следният параметър:

fetch = FetchType.EAGER

За да настроите Нетърпелив Зарежда сме използвали UserLazy близнак клас е наречен UserEager .

В следващия раздел ще разгледаме разликите между двата вида извличане.

5. Различия

Както споменахме, основната разлика между двата вида извличане е моментът, когато данните се зареждат в паметта.

Нека да разгледаме този пример:

List users = sessionLazy.createQuery("From UserLazy").list(); UserLazy userLazyLoaded = users.get(3); return (userLazyLoaded.getOrderDetail());

С подхода на мързелива инициализация orderDetailSet ще се инициализира само когато е изрично извикан с помощта на getter или някакъв друг метод, както е показано в горния пример:

UserLazy userLazyLoaded = users.get(3);

Но с нетърпелив подход в UserEager той ще бъде инициализиран незабавно в първия ред на горния пример:

List user = sessionEager.createQuery("From UserEager").list();

За лениво зареждане се използва прокси обект и се задейства отделна SQL заявка за зареждане на orderDetailSet .

Идеята за деактивиране на прокси или мързеливо зареждане се счита за лоша практика в хибернацията. Това може да доведе до много данни, които се извличат от база данни и се съхраняват в памет, независимо от необходимостта от тях.

Следният метод може да се използва за тестване на горната функционалност:

Hibernate.isInitialized(orderDetailSet);

Сега е важно да разгледате заявките, които се генерират и в двата случая:

true

Горната настройка в fetching.hbm.xml показва генерираните SQL заявки. Ако погледнете изхода на конзолата, ще можете да видите генерирани заявки.

За мързеливо зареждане на заявката, която се генерира за зареждане на потребителските данни:

select user0_.USER_ID as USER_ID1_0_, ... from USER user0_

Въпреки това, при нетърпеливо зареждане видяхме, че се направи съединение с USER_ORDER:

select orderdetai0_.USER_ID as USER_ID4_0_0_, orderdetai0_.ORDER_ID as ORDER_ID1_1_0_, orderdetai0_ ... from USER_ORDER orderdetai0_ where orderdetai0_.USER_ID=?

Горната заявка се генерира за всички потребители , което води до използването на много повече памет, отколкото при другия подход.

6. Предимства и недостатъци

6.1. Мързеливо зареждане

Предимства:

  • Първоначалното време на зареждане е много по-малко, отколкото при другия подход
  • По-малко потребление на памет, отколкото при другия подход

Disadvantages:

  • Delayed initialization might impact performance during unwanted moments
  • In some cases you need to handle lazily-initialized objects with a special care or you might end up with an exception

6.2. Eager Loading:

Advantages:

  • No delayed initialization related performance impacts

Disadvantages:

  • Long initial loading time
  • Loading too much unnecessary data might impact performance

7. Lazy Loading in Hibernate

Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes.

Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity’s class. In our example, when a requested information is missing, it will be loaded from a database before control is ceded to the User class implementation.

Трябва също да се отбележи, че когато асоциацията е представена като клас на колекция (в горните примери тя е представена като Set orderDetailSet ), тогава се създава обвивка и замества оригиналната колекция.

За да научите повече за модела на прокси дизайн, можете да се обърнете тук.

8. Заключение

В тази статия показахме примери за двата основни типа извличане, които се използват в хибернация.

За експертни познания за напреднали можете да погледнете официалния уебсайт на Hibernate. За да получите кода, обсъден в тази статия, погледнете това хранилище.

Устойчивост отдолу

Току що обявих новия курс Learn Spring , фокусиран върху основите на Spring 5 и Spring Boot 2:

>> ПРЕГЛЕД НА КУРСА