टी एल; डॉ
T findOne(ID id)
(पुराने एपीआई में नाम) / Optional<T> findById(ID id)
(नए एपीआई में नाम) पर निर्भर करता है EntityManager.find()
कि एक इकाई उत्सुक लोड हो रहा है ।
T getOne(ID id)
EntityManager.getReference()
उस पर निर्भर करता है एक इकाई आलसी लोडिंग करता है । इसलिए इकाई के प्रभावी लोडिंग को सुनिश्चित करने के लिए, इस पर एक विधि लागू करना आवश्यक है।
findOne()/findById()
की तुलना में उपयोग करने के लिए वास्तव में अधिक स्पष्ट और सरल है getOne()
।
तो मामलों की बहुत सबसे में, एहसान findOne()/findById()
से अधिक getOne()
।
एपीआई परिवर्तन
कम से कम, 2.0
संस्करण, Spring-Data-Jpa
संशोधित findOne()
।
पहले, इसे इस रूप में परिभाषित किया गया था CrudRepository
:
T findOne(ID primaryKey);
अब, आपको जो एकल findOne()
विधि मिलेगी CrudRepository
, वह QueryByExampleExecutor
इंटरफ़ेस में परिभाषित की गई है:
<S extends T> Optional<S> findOne(Example<S> example);
यह अंत SimpleJpaRepository
में CrudRepository
इंटरफ़ेस के डिफ़ॉल्ट कार्यान्वयन द्वारा कार्यान्वित किया जाता है।
यह विधि उदाहरण खोज द्वारा एक क्वेरी है और आप इसे प्रतिस्थापन के रूप में नहीं चाहते हैं।
वास्तव में, नए API में समान व्यवहार वाला तरीका अभी भी है लेकिन विधि नाम बदल गया है।
यह से नाम दिया गया था findOne()
करने के लिए findById()
में CrudRepository
इंटरफ़ेस:
Optional<T> findById(ID id);
अब यह रिटर्न ए Optional
। जिसे रोकना इतना बुरा नहीं है NullPointerException
।
तो, वास्तविक विकल्प अब Optional<T> findById(ID id)
और के बीच है T getOne(ID id)
।
दो अलग-अलग विधियाँ जो दो अलग-अलग JPA EntityManager पुनर्प्राप्ति विधियों पर निर्भर करती हैं
1) Optional<T> findById(ID id)
जावदोक में कहा गया है कि:
किसी संस्था को उसकी आईडी से वापस लेता है।
जैसा कि हम कार्यान्वयन में देखते हैं, हम देख सकते हैं कि यह EntityManager.find()
पुनर्प्राप्ति करने के लिए निर्भर करता है :
public Optional<T> findById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
Class<T> domainType = getDomainClass();
if (metadata == null) {
return Optional.ofNullable(em.find(domainType, id));
}
LockModeType type = metadata.getLockModeType();
Map<String, Object> hints = getQueryHints().withFetchGraphs(em).asMap();
return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
}
और यहाँ em.find()
एक EntityManager
विधि के रूप में घोषित किया गया है:
public <T> T find(Class<T> entityClass, Object primaryKey,
Map<String, Object> properties);
इसका जावाडॉक कहता है:
निर्दिष्ट गुणों का उपयोग करके प्राथमिक कुंजी द्वारा खोजें
इसलिए, एक भरी हुई इकाई को पुनः प्राप्त करना अपेक्षित लगता है।
2) जबकि T getOne(ID id)
जावदोक कहता है (जोर मेरा है):
दिए गए पहचानकर्ता के साथ इकाई का संदर्भ देता है ।
वास्तव में, संदर्भ शब्दावली वास्तव में बोर्ड है और जेपीए एपीआई किसी भी getOne()
विधि को निर्दिष्ट नहीं करता है ।
तो सबसे अच्छी बात यह समझने के लिए कि वसंत आवरण क्या लागू करता है:
@Override
public T getOne(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
return em.getReference(getDomainClass(), id);
}
यहाँ em.getReference()
एक EntityManager
विधि के रूप में घोषित किया गया है:
public <T> T getReference(Class<T> entityClass,
Object primaryKey);
और सौभाग्य से, EntityManager
javadoc ने अपने इरादे को बेहतर बताया (जोर मेरा है):
एक उदाहरण प्राप्त करें, जिसका राज्य आलसी हो सकता है । यदि अनुरोधित उदाहरण डेटाबेस में मौजूद नहीं है, तो EntityNotFoundException को फेंक दिया जाता है जब उदाहरण स्थिति पहले एक्सेस की जाती है । (दृढ़ता प्रदाता रनटाइम को जब EntRNference कहा जाता है तो EntityNotFoundException को फेंकने की अनुमति दी जाती है।) आवेदन को यह उम्मीद नहीं करनी चाहिए कि उदाहरण स्थिति टुकड़ी पर उपलब्ध होगी , जब तक कि यह एप्लिकेशन द्वारा एक्सेस नहीं किया गया था जब तक कि इकाई प्रबंधक खुला नहीं था।
इसलिए, आह्वान करने से getOne()
एक आलसी भ्रूण प्राप्त किया जा सकता है।
यहाँ, आलसी लाने वाले इकाई के रिश्तों को नहीं बल्कि इकाई को दर्शाता है।
इसका अर्थ है कि यदि हम आह्वान करते हैं getOne()
और फिर दृढ़ता का संदर्भ बंद हो जाता है, तो इकाई को कभी भी लोड नहीं किया जा सकता है और इसलिए परिणाम वास्तव में अप्रत्याशित है।
उदाहरण के लिए, यदि प्रॉक्सी ऑब्जेक्ट धारावाहिक है, तो आप null
धारावाहिक परिणाम के रूप में एक संदर्भ प्राप्त कर सकते हैं या यदि कोई विधि प्रॉक्सी ऑब्जेक्ट पर लागू होती है, तो अपवाद जैसे LazyInitializationException
फेंक दिया जाता है।
तो इस तरह की स्थिति में, उस थ्रो को एक इंस्टेंस को हैंडल EntityNotFoundException
करने के लिए उपयोग getOne()
करने का मुख्य कारण है जो डेटाबेस में मौजूद नहीं है क्योंकि एक त्रुटि स्थिति का प्रदर्शन कभी नहीं किया जा सकता है, जबकि इकाई मौजूद नहीं है।
किसी भी स्थिति में, इसकी लोडिंग सुनिश्चित करने के लिए आपको सत्र को खोलते समय इकाई में हेरफेर करना होगा। आप इसे इकाई पर किसी भी विधि को लागू करके कर सकते हैं।
या findById(ID id)
इसके बजाय एक बेहतर वैकल्पिक उपयोग ।
इतना अस्पष्ट एपीआई क्यों?
समाप्त करने के लिए, स्प्रिंग-डेटा-जेपीए डेवलपर्स के लिए दो प्रश्न:
क्यों नहीं के लिए एक स्पष्ट दस्तावेज होने getOne()
? इकाई आलसी लोडिंग वास्तव में एक विस्तार नहीं है।
आपको getOne()
लपेटने की आवश्यकता क्यों है EM.getReference()
?
बस लिपटे विधि से क्यों न चिपके getReference()
:? यह ईएम विधि वास्तव में बहुत खास है जबकि getOne()
इतनी सरल प्रक्रिया को व्यक्त करती है।