मैं जावा पर्सिस्टेंस एपीआई और हाइबरनेट के लिए नौसिखिया हूं।
के बीच क्या अंतर है FetchType.LAZY
FetchType.EAGER
जावा पर्सिस्टेंस एपीआई में और है?
मैं जावा पर्सिस्टेंस एपीआई और हाइबरनेट के लिए नौसिखिया हूं।
के बीच क्या अंतर है FetchType.LAZY
FetchType.EAGER
जावा पर्सिस्टेंस एपीआई में और है?
जवाबों:
कभी-कभी आपके पास दो संस्थाएँ होती हैं और उनके बीच एक संबंध होता है। उदाहरण के लिए, आपके पास एक संस्था हो सकती है जिसे University
दूसरी इकाई कहा जाता हैStudent
जा सकता है और एक विश्वविद्यालय में कई छात्र हो सकते हैं:
विश्वविद्यालय की इकाई में कुछ मूल गुण हो सकते हैं जैसे आईडी, नाम, पता इत्यादि और साथ ही एक संग्रह संपत्ति, जिसे छात्रों को दिया जाता है जो किसी दिए गए विश्वविद्यालय के लिए छात्रों की सूची लौटाते हैं:
public class University {
private String id;
private String name;
private String address;
private List<Student> students;
// setters and getters
}
अब जब आप डेटाबेस से एक विश्वविद्यालय को लोड करते हैं, तो जेपीए आपके लिए अपना आईडी, नाम और पता फ़ील्ड लोड करता है। लेकिन आपके पास दो विकल्प हैं कि छात्रों को कैसे लोड किया जाना चाहिए:
getStudents()
विधि कहते हैं तो इसे ऑन-डिमांड (यानी आलसी) लोड करने के लिए ।जब एक विश्वविद्यालय में कई छात्र होते हैं, तो अपने सभी छात्रों को इसके साथ लोड करने के लिए कुशल नहीं होता है, खासकर जब उन्हें ज़रूरत नहीं होती है और इस तरह के मामलों में आप यह घोषणा कर सकते हैं कि आप चाहते हैं कि छात्र वास्तव में ज़रूरत पड़ने पर लोड हो सकें। इसे आलसी लोडिंग कहा जाता है।
यहां एक उदाहरण है, जहां students
स्पष्ट रूप से उत्सुकता से लोड होने के लिए चिह्नित किया गया है:
@Entity
public class University {
@Id
private String id;
private String name;
private String address;
@OneToMany(fetch = FetchType.EAGER)
private List<Student> students;
// etc.
}
और यहाँ एक उदाहरण है जहाँ students
स्पष्ट रूप से लोड किए जाने के लिए स्पष्ट रूप से चिह्नित किया गया है:
@Entity
public class University {
@Id
private String id;
private String name;
private String address;
@OneToMany(fetch = FetchType.LAZY)
private List<Student> students;
// etc.
}
getStudents()
) को लागू करके मेमोरी में लोड करना चाहते हैं , लेकिन कभी-कभी यह संभव नहीं होता है, क्योंकि इस विधि द्वारा कहा जाता है, सत्र पहले से ही बंद है और इकाई अलग है। इसी तरह, कभी-कभी हमारे पास एक क्लाइंट / सर्वर आर्किटेक्चर (जैसे स्विंग क्लाइंट / जेईई सर्वर) और एंटिटीज / डीटीओ ग्राहक के तार पर स्थानांतरित हो जाते हैं और फिर से इन परिदृश्यों में सबसे अधिक बार आलसी लोडिंग के कारण काम नहीं करेगा। तार पर क्रमबद्ध हैं।
getStudents()
पहली बार विधि कहता हूं , तो परिणाम कैश्ड हैं? ताकि मैं अगली बार उन परिणामों तक तेजी से पहुंच सकूं?
EAGER
संग्रह को लोड करने का अर्थ है कि वे उस समय पूरी तरह से अपने माता-पिता के लिए लाए गए हैं। इसलिए यदि आपके पास है Course
और यह है List<Student>
, तो उस समय सभी छात्रों को डेटाबेस से Course
लाया जाता है।
LAZY
दूसरी ओर इसका मतलब है कि सामग्री List
तभी प्राप्त होती है जब आप उन्हें एक्सेस करने का प्रयास करते हैं। उदाहरण के लिए, कॉल करके course.getStudents().iterator()
। List
तत्वों को पुनः प्राप्त करने के लिए डेटाबेस पर किसी भी एक्सेस विधि को कॉल करने से एक कॉल शुरू होगी। यह List
(या Set
) के चारों ओर एक प्रॉक्सी बनाकर कार्यान्वित किया जाता है । तो अपने आलसी संग्रह के लिए, ठोस प्रकार ArrayList
और नहीं हैं HashSet
, लेकिन PersistentSet
और PersistentList
(या PersistentBag
)
course.getStudents()
, तो यह एक SQL क्वेरी (कंसोल पर देखा गया है) को फायर करता है। आलसी प्रकार में भी, एक ही बात होती है। तो, क्या अंतर है ??
fetchtype = LAZY
डिफ़ॉल्ट पर सेट है , भले ही गेटर हाइबरनेट के साथ संग्रह प्राप्त करने की कोशिश करें, यह बताने में त्रुटि होती है कि यह मूल्यांकन नहीं कर सकता है
मैं प्रदर्शन और स्मृति उपयोग पर विचार कर सकता हूं। एक बड़ा अंतर यह है कि EAGER लाने की रणनीति सत्र के बिना प्राप्त डेटा ऑब्जेक्ट का उपयोग करने की अनुमति देती है। क्यों?
सत्र कनेक्ट होने पर ऑब्जेक्ट में उत्सुक चिह्नित डेटा होने पर सभी डेटा प्राप्त होते हैं। हालांकि, आलसी लोडिंग रणनीति के मामले में, आलसी लोडिंग चिह्नित ऑब्जेक्ट सत्र को डिस्कनेक्ट होने पर ( session.close()
कथन के बाद ) डेटा पुनर्प्राप्त नहीं करता है । वह सब हाइबरनेट प्रॉक्सी द्वारा किया जा सकता है। ईगर रणनीति सत्र समापन के बाद भी डेटा उपलब्ध होने देती है।
डिफ़ॉल्ट रूप से, सभी संग्रह और मानचित्र वस्तुओं के लिए भ्रूण का नियम है FetchType.LAZY
और अन्य उदाहरणों के लिए यह FetchType.EAGER
नीति का पालन करता है ।
संक्षेप में, @OneToMany
और @ManyToMany
संबंध संबंधित वस्तुओं (संग्रह और मानचित्र) को स्पष्ट रूप से प्राप्त नहीं करते हैं, लेकिन पुनर्प्राप्ति ऑपरेशन को क्षेत्र के माध्यम से कैस्केड किया जाता है @OneToOne
और@ManyToOne
लोगों के है।
दोनों FetchType.LAZY
और FetchType.EAGER
परिभाषित किया जाता है डिफ़ॉल्ट योजना लाने ।
दुर्भाग्य से, आप केवल LAZY लाने के लिए डिफ़ॉल्ट लाने की योजना को ओवरराइड कर सकते हैं। EAGER लाने कम लचीला है और कई प्रदर्शन मुद्दों को जन्म दे सकता है ।
मेरी सलाह है कि अपने संघों को ईएजीईआर बनाने के आग्रह पर लगाम लगाएं क्योंकि एक प्रश्नोत्तर ज़िम्मेदारी है। इसलिए आपके सभी प्रश्नों को केवल वर्तमान व्यवसाय के मामले के लिए आवश्यक होने के लिए पुनः प्राप्त करने के लिए लाने के निर्देश का उपयोग करना चाहिए ।
से जावाडोक :
EAGER रणनीति दृढ़ता प्रदाता रनटाइम पर एक आवश्यकता है जिसे डेटा को उत्सुकता से प्राप्त किया जाना चाहिए। LAZY रणनीति दृढ़ता प्रदाता रनटाइम के लिए एक संकेत है कि जब यह पहली बार एक्सेस किया जाता है तो डेटा को आलसी रूप से प्राप्त किया जाना चाहिए।
जैसे, आलसी की तुलना में उत्सुक अधिक सक्रिय है। आलसी केवल पहले उपयोग पर होता है (यदि प्रदाता संकेत लेता है), जबकि उत्सुक चीजों के साथ (पूर्व) प्राप्त हो सकता है।
Lazy
लायें प्रकार हाइबरनेट द्वारा चयनित जब तक आप स्पष्ट निशान डिफ़ॉल्ट रूप से हैEager
प्रकार लायें। अधिक सटीक और संक्षिप्त होने के लिए, अंतर को नीचे बताया जा सकता है।
FetchType.LAZY
= यह रिश्तों को तब तक लोड नहीं करता है जब तक आप इसे गेट्टर विधि के माध्यम से नहीं करते हैं।
FetchType.EAGER
= यह सभी रिश्तों को लोड करता है।
इन दो प्रकारों के पेशेवरों और विपक्ष।
Lazy initialization
अनावश्यक संगणना से बचने और स्मृति आवश्यकताओं को कम करके प्रदर्शन में सुधार करता है।
Eager initialization
अधिक मेमोरी खपत और प्रसंस्करण की गति धीमी है।
कहा गया है कि, स्थिति पर निर्भर करता है कि इनमें से किसी एक का उपयोग किया जा सकता है।
getMember
है जो सदस्य के नाम पैटर्न से बिल्कुल मेल खाता है?
Book.java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="Books")
public class Books implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="book_id")
private int id;
@Column(name="book_name")
private String name;
@Column(name="author_name")
private String authorName;
@ManyToOne
Subject subject;
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
}
Subject.java
import java.io.Serializable;
import java.util.ArrayList;
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.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name="Subject")
public class Subject implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="subject_id")
private int id;
@Column(name="subject_name")
private String name;
/**
Observe carefully i have mentioned fetchType.EAGER. By default its is fetchType.LAZY for @OneToMany i have mentioned it but not required. Check the Output by changing it to fetchType.EAGER
*/
@OneToMany(mappedBy="subject",cascade=CascadeType.ALL,fetch=FetchType.LAZY,
orphanRemoval=true)
List<Books> listBooks=new ArrayList<Books>();
public List<Books> getListBooks() {
return listBooks;
}
public void setListBooks(List<Books> listBooks) {
this.listBooks = listBooks;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
HibernateUtil.java
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory ;
static {
Configuration configuration = new Configuration();
configuration.addAnnotatedClass (Com.OneToMany.Books.class);
configuration.addAnnotatedClass (Com.OneToMany.Subject.class);
configuration.setProperty("connection.driver_class","com.mysql.jdbc.Driver");
configuration.setProperty("hibernate.connection.url", "jdbc:mysql://localhost:3306/hibernate");
configuration.setProperty("hibernate.connection.username", "root");
configuration.setProperty("hibernate.connection.password", "root");
configuration.setProperty("dialect", "org.hibernate.dialect.MySQLDialect");
configuration.setProperty("hibernate.hbm2ddl.auto", "update");
configuration.setProperty("hibernate.show_sql", "true");
configuration.setProperty(" hibernate.connection.pool_size", "10");
configuration.setProperty(" hibernate.cache.use_second_level_cache", "true");
configuration.setProperty(" hibernate.cache.use_query_cache", "true");
configuration.setProperty(" cache.provider_class", "org.hibernate.cache.EhCacheProvider");
configuration.setProperty("hibernate.cache.region.factory_class" ,"org.hibernate.cache.ehcache.EhCacheRegionFactory");
// configuration
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
sessionFactory = configuration.buildSessionFactory(builder.build());
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Main.java
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory factory=HibernateUtil.getSessionFactory();
save(factory);
retrieve(factory);
}
private static void retrieve(SessionFactory factory) {
Session session=factory.openSession();
try{
session.getTransaction().begin();
Subject subject=(Subject)session.get(Subject.class, 1);
System.out.println("subject associated collection is loading lazily as @OneToMany is lazy loaded");
Books books=(Books)session.get(Books.class, 1);
System.out.println("books associated collection is loading eagerly as by default @ManyToOne is Eagerly loaded");
/*Books b1=(Books)session.get(Books.class, new Integer(1));
Subject sub=session.get(Subject.class, 1);
sub.getListBooks().remove(b1);
session.save(sub);
session.getTransaction().commit();*/
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
private static void save(SessionFactory factory){
Subject subject=new Subject();
subject.setName("C++");
Books books=new Books();
books.setAuthorName("Bala");
books.setName("C++ Book");
books.setSubject(subject);
subject.getListBooks().add(books);
Session session=factory.openSession();
try{
session.beginTransaction();
session.save(subject);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
session.close();
}
}
}
Main.java की पुनर्प्राप्त () विधि की जाँच करें। जब हमें Subject मिलता है, तो इसके संग्रह सूची , के साथ एनोटेट किया जाता है @OneToMany
, इसे आलसी लोड किया जाएगा। लेकिन, दूसरे हाथ पर, किताबें संबंधित संग्रह के सहयोग से विषय , के साथ एनोटेट @ManyToOne
, भार eargerly (द्वारा [default][1]
के लिए @ManyToOne
, fetchType=EAGER
)। हम Books.java में @OneToMany
Subject.java या fetchType.LAZY पर fetchType.EAGER रखकर व्यवहार को बदल सकते हैं @ManyToOne
।
public enum FetchType, java.lang.Enum को बढ़ाता है, जो डेटाबेस से डेटा लाने के लिए रणनीतियों को परिभाषित करता है। EAGER रणनीति दृढ़ता प्रदाता रनटाइम पर एक आवश्यकता है जिसे डेटा को उत्सुकता से प्राप्त किया जाना चाहिए। LAZY रणनीति दृढ़ता प्रदाता रनटाइम के लिए एक संकेत है कि जब इसे पहली बार एक्सेस किया जाता है तो डेटा को आलसी रूप से प्राप्त किया जाना चाहिए। कार्यान्वयन को उत्सुकता से डेटा प्राप्त करने की अनुमति है जिसके लिए LAZY रणनीति संकेत निर्दिष्ट किया गया है। उदाहरण: @Basic (fetch = LAZY) संरक्षित स्ट्रिंग getName () {रिटर्न नाम; }
मैं इस नोट को "क्युंग ह्वेन मिन" के ऊपर जोड़ना चाहता हूं।
मान लीजिए कि आप इस साधारण वास्तुकार के साथ स्प्रिंग रेस्ट का उपयोग कर रहे हैं:
नियंत्रक <-> सेवा <-> भंडार
और आप कुछ डेटा को फ्रंट-एंड पर लौटना चाहते हैं, यदि आप उपयोग कर रहे हैं, तो आपको FetchType.LAZY
नियंत्रक विधि में डेटा वापस करने के बाद एक अपवाद मिलेगा क्योंकि सत्र सेवा में बंद हैJSON Mapper Object
डेटा नहीं मिल सकता है।
इस समस्या को हल करने के लिए तीन सामान्य विकल्प हैं, डिजाइन, प्रदर्शन और डेवलपर पर निर्भर करता है:
FetchType.EAGER
, ताकि सत्र अभी भी नियंत्रक विधि पर जीवित रहेगा।FetchType.LAZY
से डेटा स्थानांतरित Entity
करने और DTO
इसे नियंत्रक को भेजने के लिए कनवर्टर विधि के साथ उपयोग करने के लिए सबसे अच्छा अभ्यास है , इसलिए सत्र बंद होने पर कोई अपवाद नहीं है।@ ड्रॉप-शैडो यदि आप हाइबरनेट का उपयोग कर रहे हैं, तो विधि के Hibernate.initialize()
आह्वान पर आप कॉल कर सकते हैं getStudents()
:
Public class UniversityDaoImpl extends GenericDaoHibernate<University, Integer> implements UniversityDao {
//...
@Override
public University get(final Integer id) {
Query query = getQuery("from University u where idUniversity=:id").setParameter("id", id).setMaxResults(1).setFetchSize(1);
University university = (University) query.uniqueResult();
***Hibernate.initialize(university.getStudents());***
return university;
}
//...
}
LAZY: यह बाल संस्थाओं को आलसी बनाता है अर्थात माता-पिता की संस्था को लाने के समय यह सिर्फ बाल संस्थाओं की प्रॉक्सी (cglib या किसी अन्य उपयोगिता द्वारा निर्मित) को प्राप्त करता है और जब आप बाल इकाई की किसी भी संपत्ति का उपयोग करते हैं तो यह वास्तव में हाइबरनेट द्वारा लाया जाता है।
EAGER: यह माता-पिता के साथ-साथ बाल संस्थाओं को भी लाता है।
बेहतर समझ के लिए Jboss प्रलेखन पर जाएं या आप hibernate.show_sql=true
अपने ऐप के लिए उपयोग कर सकते हैं और हाइबरनेट द्वारा जारी किए गए प्रश्नों की जांच कर सकते हैं ।