Току що обявих новия курс 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. За да получите кода, обсъден в тази статия, погледнете това хранилище.
Устойчивост отдолу