हाइबरनेट एनोटेशन - कौन सा बेहतर है, क्षेत्र या संपत्ति का उपयोग?


134

यह प्रश्न कुछ हद तक हाइबरनेट एनोटेशन प्लेसमेंट प्रश्न से संबंधित है ।

लेकिन मैं जानना चाहता हूं कि कौन सा बेहतर है ? गुणों के माध्यम से या खेतों के माध्यम से पहुंच? हर एक के फायदे और नुकसान क्या हैं?

जवाबों:


33

मुझे एक्सेसर्स पसंद हैं, क्योंकि मुझे जब भी ज़रूरत होती है मैं अपने एक्सेसर्स में कुछ व्यावसायिक तर्क जोड़ सकता हूं। यहाँ एक उदाहरण है:

@Entity
public class Person {

  @Column("nickName")
  public String getNickName(){
     if(this.name != null) return generateFunnyNick(this.name);
     else return "John Doe";
  }
}

इसके अलावा, यदि आप मिक्स में एक और परिवाद फेंकते हैं (जैसे कुछ JSON-कन्वर्टिंग लिब या BeanMapper या डोजर या अन्य बीन मैपिंग / क्लंटर लीवर जो गटर / सेटर प्रॉपर्टी के आधार पर होता है) तो आपको यह गारंटी होगी कि परिवाद दृढ़ता के साथ सिंक में है प्रबंधक (दोनों गेट्टर / सेटर का उपयोग करते हैं)।


17
ध्यान दें कि यह इस बारे में है कि ORM आपके फ़ील्ड्स / प्रॉपर्टीज़ तक कैसे पहुँचता है न कि आपके एप्लिकेशन कोड के बारे में। फ़ील्ड एक्सेस के साथ आपका getNickName () विधि ठीक उसी तरह काम करेगी जैसी आप अपेक्षा करते हैं। यदि आप गेटर्स / सेटर के बाहर लगातार 'गुणों' का उपयोग करते हैं तो यह सच नहीं है। यह वह जगह है जहाँ आप संपत्ति के उपयोग और आलसी लोडिंग के साथ मुद्दों को हिट कर सकते हैं। तो नहीं, मैं सामान्य रूप से इस तर्क से सहमत नहीं हूं। हालाँकि, पिछली बार जब मैंने चेक किया था कि हाइबरनेट में @Id फ़ील्ड्स के फ़ील्ड एक्सेस के मुद्दे थे।
रोब Bygrave

11
यह उत्तर प्रश्न से संबंधित नहीं है। Duffymo द्वारा सर्वश्रेष्ठ उत्तर
Janning

9
एक्सेसर्स के अंदर कोई व्यावसायिक तर्क नहीं होना चाहिए। यह स्पष्ट व्यवहार नहीं है।
इयूरीसुक सिप

यह प्रतिक्रिया चिह्न सही क्यों है? यह सही नहीं है कि आप फ़ील्ड की मैपिंग कर सकते हैं और इसे उसी तरह सेटर / गेट्टर प्रदान कर सकते हैं।
Lucke

246

दोनों के लिए तर्क हैं, लेकिन उनमें से अधिकांश कुछ उपयोगकर्ता की आवश्यकताओं से स्टेम करते हैं "क्या होगा यदि आपको तर्क जोड़ने की आवश्यकता है", या "xxxx इनकैप्सुलेशन को तोड़ता है"। हालांकि, किसी ने वास्तव में सिद्धांत पर टिप्पणी नहीं की है, और एक उचित तर्क दिया है।

हाइबरनेट / जेपीए वास्तव में क्या कर रहा है जब यह एक वस्तु को बनाए रखता है - अच्छी तरह से, यह वस्तु की स्थिति को बनाए रखता है। इसका मतलब है कि इसे इस तरह से संग्रहीत करना कि इसे आसानी से पुन: पेश किया जा सके।

एनकैप्सुलेशन क्या है? एनकैप्सुलेशन का अर्थ है कि डेटा (या राज्य) को एक इंटरफेस के साथ इनकैप्सुलेट करना जो एप्लिकेशन / क्लाइंट डेटा को सुरक्षित रूप से एक्सेस करने के लिए उपयोग कर सकते हैं - इसे लगातार और वैध रखते हुए।

इसे MS Word की तरह समझें। एमएस वर्ड मेमोरी में दस्तावेज़ का एक मॉडल रखता है - दस्तावेज़ स्टेट। यह एक इंटरफ़ेस प्रस्तुत करता है जिसे उपयोगकर्ता दस्तावेज़ को संशोधित करने के लिए उपयोग कर सकता है - बटन, उपकरण, कीबोर्ड कमांड आदि का एक सेट। हालांकि, जब आप उस दस्तावेज़ को जारी रखना (सहेजना) चुनते हैं, तो यह आंतरिक स्थिति को बचाता है, न कि कीप्स का सेट और इसे उत्पन्न करने के लिए माउस क्लिक का उपयोग किया जाता है।

ऑब्जेक्ट की आंतरिक स्थिति को सहेजना, एनकैप्सुलेशन को नहीं तोड़ता है - अन्यथा आप वास्तव में समझ नहीं पाते हैं कि एनकैप्सुलेशन का अर्थ क्या है, और यह क्यों मौजूद है। यह वास्तव में वस्तु क्रमांकन जैसा है।

इस कारण से, अधिकांश मामलों में, यह FIELDS को बनाए रखने के लिए उपयुक्त है, न कि ACCESSORS के। इसका मतलब है कि किसी ऑब्जेक्ट को डेटाबेस से ठीक उसी तरह से फिर से बनाया जा सकता है जिस तरह से संग्रहीत किया गया था। इसे किसी भी सत्यापन की आवश्यकता नहीं है, क्योंकि यह मूल पर किया गया था जब इसे बनाया गया था, और इससे पहले कि यह डेटाबेस में संग्रहीत किया गया था (जब तक, भगवान न करे, आप डीबी में अमान्य डेटा संग्रहीत कर रहे हैं !!!!)। इसी तरह, मूल्यों की गणना करने की कोई आवश्यकता नहीं होनी चाहिए, क्योंकि वे पहले ही गणना की गई थीं कि ऑब्जेक्ट को संग्रहीत किया गया था। ऑब्जेक्ट को सहेजने से पहले बस उसी तरह दिखना चाहिए जैसे उसने किया था। वास्तव में, गेटर्स / सेटर में अतिरिक्त सामान जोड़कर आप वास्तव में जोखिम बढ़ा रहे हैं कि आप कुछ ऐसा बनाएंगे जो मूल की सटीक प्रतिलिपि नहीं है।

बेशक, इस कार्यक्षमता को एक कारण के लिए जोड़ा गया था। एक्सेसरों को जारी रखने के लिए कुछ वैध उपयोग के मामले हो सकते हैं, हालांकि, वे आम तौर पर दुर्लभ होंगे। एक उदाहरण यह हो सकता है कि आप एक परिकलित मान को बनाए रखने से बचना चाहते हैं, हालांकि आप यह सवाल पूछना चाहते हैं कि आप मूल्य के गेटर में मांग पर इसकी गणना क्यों नहीं करते हैं, या इसे प्राप्त करने वाले में आलस्य करते हैं। व्यक्तिगत रूप से मैं किसी भी अच्छे उपयोग के मामले के बारे में नहीं सोच सकता, और यहाँ कोई भी उत्तर वास्तव में "सॉफ्टवेयर इंजीनियरिंग" उत्तर नहीं देता है।


9
सॉफ्टवेयर इंजीनियरिंग का उत्तर है: एक्सेसर्स का उपयोग करना DRY का उल्लंघन करता है।
sourcedelica

1
@ मैं आपके उत्तर के अंतिम पैराग्राफ के बारे में अनुवर्ती प्रश्न रखता हूं। आपने लिखा "एक उदाहरण यह हो सकता है कि आप एक परिकलित मान को बनाए रखने से बचना चाहते हैं"। आप संपत्ति आधारित पहुंच के द्वारा परिकलित मान को बनाए रखने से कैसे बच सकते हैं? मैं जानता हूं कि आप ऐसा नहीं करने के लिए बहस कर रहे हैं लेकिन मुझे यहां बात नहीं मिल रही है। क्या आप समझा सकते हैं?
गीक

4
@ गीक अब जब मैंने इसे वापस पढ़ा तो मुझे खुद पर पूरा यकीन नहीं है। यह जवाब लिखने के बाद से मुझे दो साल हो गए। मुझे लगता है कि एक बेहतर उदाहरण हो सकता है कि आप एक विरासत डेटाबेस के साथ काम कर रहे हैं, और डेटा आपके ऑब्जेक्ट मॉडल के लिए एक अलग तरीके से प्रस्तुत किया गया है - एक्सेसर्स दोनों के बीच एक मैपिंग प्रदान कर सकते हैं।
मार्टिन

23
एक्सेसर्स की मैपिंग के लिए एक अच्छा उपयोग मामला तब है जब आपको तृतीय-पक्ष इकाई वर्गों के उपवर्गों में मैपिंग जानकारी जोड़ने की आवश्यकता होती है जो किसी भी दृढ़ता कार्यान्वयन के लिए बंधे नहीं होते हैं। चूंकि उन वर्गों में फ़ील्ड निजी हैं, इसलिए आपको एक्सेसर्स को ओवरराइड करना होगा और उन पर मैपिंग एनोटेशन जोड़ना होगा। एक अन्य विकल्प XML मैपिंग का उपयोग करना होगा, लेकिन कुछ चीजें वहां करना बहुत कठिन हैं। इसलिए, यदि आप एनोटेशन चाहते हैं और थर्ड-पार्टी क्लासेस को मैप करते हैं, तो उन्हें सबक्लास करना और एक्सेसर्स पर एनोटेशन जोड़ना शामिल है।
एलेन अब्दुर्रखिमोव

5
@ElnurAbdurrakhimov हम एक उत्कृष्ट उदाहरण हैं। धन्यवाद।
मार्टिन

79

मैं फील्ड एक्सेस पसंद करता हूं, क्योंकि इस तरह मैं प्रत्येक संपत्ति के लिए गेटटर / सेटर प्रदान करने के लिए मजबूर नहीं हूं।

Google के माध्यम से एक त्वरित सर्वेक्षण बताता है कि फ़ील्ड एक्सेस बहुसंख्यक है (जैसे, http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype )।

मेरा मानना ​​है कि फ़ील्ड एक्सेस स्प्रिंग द्वारा अनुशंसित मुहावरा है, लेकिन मैं इसे वापस करने के लिए एक संदर्भ नहीं पा सकता हूं।

एक संबंधित SO प्रश्न है जो प्रदर्शन को मापने की कोशिश करता है और इस निष्कर्ष पर पहुंचा कि "कोई अंतर नहीं है"।


यदि आप इकाई में सेटर गेटर प्रदान नहीं करते हैं, तो उस फ़ील्ड का उपयोग क्या है ... आप इसे एप्लिकेशन में उपयोग नहीं कर सकते, डेस्यूज़ फ़ील्ड निजी हैं
anshulkatta

1
क्या आपके क्षेत्र की खराब प्रैक्टिस के लिए कोई गेटटर और सेटर उपलब्ध नहीं करा रहा है? मुझे लगता है कि मेरी टिप्पणी यहाँ हमेशा सही नहीं है, क्योंकि मैं एक सार्वजनिक क्षेत्र ग्रहण कर रहा था, जबकि यह स्पष्ट रूप से एक निजी क्षेत्र हो सकता है जो कभी एक्सेस नहीं किया जाता है।
मैथिज्स सीजर

3
@anshulkatta मुझे लगता है कि मुझे वास्तव में आपके सवालों का समाधान करना चाहिए, क्योंकि इन सबका क्या मतलब है। आदर्श रूप से आपके सभी क्षेत्र निजी होने चाहिए, और यदि संभव हो तो उनके पास कोई गेटर्स या सेटर नहीं होना चाहिए - यही सबसे अच्छा स्तर है, जिसकी आप उम्मीद कर सकते हैं। एक पासवर्ड चेकर पर विचार करें। 2 निजी फ़ील्ड पासवर्डहैश और विफल प्रयास। दोनों बिना गेटटर या सेटर के निजी हो सकते हैं। इनका उपयोग बूल चेकपासवर्ड (स्ट्रिंग पासवर्ड) द्वारा किया जाता है, जो हैश करता है, पासवर्ड के खिलाफ जांच करता है और फिर विफल हो जाता है। अपडेट विफल रहता है और परिणाम देता है। कभी भी उन दो क्षेत्रों तक पहुँचने के लिए अन्य कोड की आवश्यकता नहीं है।
मार्टिन

2
@anshulkatta यह ध्यान दिया जाना चाहिए कि ओओपी में, गेटर्स और सेटर एक विरोधी पैटर्न हैं, वे प्रक्रियात्मक प्रोग्रामिंग से आते हैं, उनके साथ एक क्लास होने से एन्कैप्सुलेशन सिद्धांत टूट जाता है, और बहुत सारे बॉयलरप्लेट कोड उत्पन्न होते हैं, जो एक ही तरह का होता है। बार-बार कोड दोहराया गया। वस्तुओं को अपरिवर्तनीय होना चाहिए, यदि इसके गुणों के संशोधन की आवश्यकता है तो इसे विधि के माध्यम से किया जाना चाहिए जो संपत्ति के मूल्य को वापस करने से अधिक कुछ करते हैं।
उरेल अरविजु

ऐसा नहीं। इस मामले में "विरोधी पैटर्न" विचार का विषय है, न कि हठधर्मिता का। उस के साथ, क्षेत्र का उपयोग अभी भी पसंद किया जाता है। एक बेहतर विचार है कि ओआरएम समाधानों से पूरी तरह से दूर रहें। उचित SQL लिखना सीखें।
डफिमो

38

यहां ऐसी स्थिति है जहां आपको संपत्ति एक्सेसरों का उपयोग करना है। कल्पना कीजिए कि आपके पास एक सामान्य सार वर्ग है जिसमें 8 ठोस उपवर्गों में विरासत के लिए बहुत सारी कार्यान्वयन अच्छाई है:

public abstract class Foo<T extends Bar> {

    T oneThing;
    T anotherThing;

    // getters and setters ommited for brevity

    // Lots and lots of implementation regarding oneThing and anotherThing here
 }

अब वास्तव में आपको इस वर्ग की व्याख्या कैसे करनी चाहिए? इसका उत्तर है कि आप इसे किसी भी क्षेत्र या संपत्ति के उपयोग के साथ नहीं बता सकते क्योंकि आप इस बिंदु पर लक्ष्य इकाई को निर्दिष्ट नहीं कर सकते। आपको ठोस कार्यान्वयन की व्याख्या करनी है। लेकिन जब से इस सुपरक्लास में लगातार संपत्तियों की घोषणा की जाती है, तो आपको उपवर्गों में संपत्ति का उपयोग करना होगा।

एब्सट्रैक्ट जेनेरिक सुपर-क्लास वाले एप्लिकेशन में फ़ील्ड एक्सेस एक विकल्प नहीं है।


2
टच। मैंने ऐसा नहीं सोचा था। मुझे विश्वास है कि हाइबरनेट इन के लिए कुछ पागल एसक्यूएल बाहर निकालता है।
जोसफ वास

8
यह समस्या गुणों को एनोटेट किए बिना हल करने के लिए यंत्रवत् रूप से कठिन लगती है, लेकिन मैं कभी ऐसे मामले में नहीं भागा हूं जहां मुझे बहुत सारे कार्यान्वयन के साथ एक सार सामान्य वर्ग की आवश्यकता थी जिसे मैं भी जारी रखना चाहता था। आमतौर पर मैं अपनी वस्तु पॉलीमॉर्फिक बनाने के लिए एक वर्ग पदानुक्रम बनाता हूं (जो इसे सामान्य प्रकार का विराम बनाता है), और केवल कोड पुन: उपयोग के लिए नहीं। और "बहुत सारे और बहुत सारे कार्यान्वयन" अक्सर एसआरपी का उल्लंघन करते हैं वैसे भी, इस मामले में मैं शायद इसे अलग-अलग वर्गों में स्थानांतरित कर दूंगा। क्या कोई ठोस उदाहरण है जो इस उपयोग के मामले को अधिक स्पष्ट करता है?
मर्लिन मॉर्गन-ग्राहम

मेरे पास एकमात्र ठोस उदाहरण मेरा आवेदन है, जिसे मैं एक 500 चरित्र टिप्पणी में वर्णित नहीं कर सकता; ;-)
HDave

3
आप फ़ील्ड एक्सेस का उपयोग कर सकते हैं abstract T getOneThing(), और कर सकते हैं abstract void setOneThing(T thing)
आर्टुरो वोल्प

33

मैं संपत्ति एक्सेसरों को प्राथमिकता देना और उनका उपयोग करना चाहता हूं:

  • जरूरत पड़ने पर मैं तर्क जोड़ सकता हूं (जैसा कि स्वीकृत उत्तर में बताया गया है)।
  • यह मुझे foo.getId() प्रॉक्सी को शुरू किए बिना कॉल करने की अनुमति देता है (हाइबरनेट का उपयोग करते समय महत्वपूर्ण, जब तक कि HHH-3718 हल न हो जाए)।

दोष यह है:

  • यह कोड को कम पठनीय बनाता है, उदाहरण के लिए आपके पास एक पूरी कक्षा ब्राउज़ करने के लिए है कि क्या वहां @Transientआसपास हैं।

लेकिन तब यदि आप एक जेपीए प्रदाता का उपयोग करते हैं जिसमें "प्रॉक्सी" नहीं है, तो आपको वह समस्या उर्फ ​​"आपका जेपीए प्रदाता आप पर थोप रहा है" नहीं है।
नील स्टॉकटन

13

यह वास्तव में एक विशिष्ट मामले पर निर्भर करता है - दोनों विकल्प एक कारण के लिए उपलब्ध हैं। IMO इसे तीन मामलों में उबालता है:

  1. सेटर के पास कुछ तर्क होते हैं जिन्हें डेटाबेस से उदाहरण लोड करने के समय निष्पादित नहीं किया जाना चाहिए; उदाहरण के लिए, कुछ मान सत्यापन सेटर में होता है, हालाँकि db से आने वाला डेटा वैध होना चाहिए (अन्यथा यह वहाँ नहीं मिलेगा: (;)), इस मामले में फ़ील्ड एक्सेस सबसे उपयुक्त है;
  2. सेटर में कुछ तर्क होते हैं, जिन्हें हमेशा db से एक इंस्टेंस को लोड करने के दौरान भी लागू किया जाना चाहिए; उदाहरण के लिए, प्रारंभिक की जा रही संपत्ति का उपयोग कुछ गणना क्षेत्र की गणना में किया जाता है (जैसे संपत्ति - एक मौद्रिक राशि, गणना की गई संपत्ति - एक ही उदाहरण के कई मौद्रिक गुणों का कुल); इस स्थिति में संपत्ति की पहुँच आवश्यक है।
  3. उपरोक्त मामलों में से कोई भी - फिर दोनों विकल्प लागू होते हैं, बस सुसंगत रहें (ईई यदि इस स्थिति में फ़ील्ड का उपयोग पसंद है तो हर समय समान स्थिति में इसका उपयोग करें)।

मैं हाइबरनेट के लिए नया हूं और उसी सवाल से जूझ रहा हूं। मुझे लगता है कि यह पोस्ट सबसे स्पष्ट उत्तर प्रदान करती है। धन्यवाद।
सैम लेविन

12

यदि आप बस मान (जैसे एन्क्रिप्शन या गणना) निर्धारित करने की तुलना में बसों में अधिक कुछ करना चाहते हैं, तो मैं दृढ़ता से फ़ील्ड एक्सेस और गेटर्स (प्रॉपर्टी एक्सेस) पर एनोटेशन की सिफारिश नहीं करूंगा।

संपत्ति के उपयोग के साथ समस्या यह है कि बसने वाले को तब भी कहा जाता है जब ऑब्जेक्ट लोड होता है। यह मेरे लिए कई महीनों तक ठीक काम किया है जब तक हम एन्क्रिप्शन शुरू नहीं करना चाहते थे। हमारे उपयोग के मामले में हम सेटर में एक फ़ील्ड को एन्क्रिप्ट करना चाहते हैं और इसे गेटटर में डिक्रिप्ट करते हैं। प्रॉपर्टी ऐक्सेस के साथ अब समस्या यह थी कि जब हाइबरनेट ने ऑब्जेक्ट को लोड किया था तो वह फ़ील्ड को पॉप्युलेट करने के लिए सेटर को भी बुला रहा था और इस तरह एन्क्रिप्टेड वैल्यू को फिर से एन्क्रिप्ट कर रहा था। इस पोस्ट में यह भी उल्लेख किया गया है: जावा हाइबरनेट: अलग-अलग प्रॉपर्टी सेट फ़ंक्शन के व्यवहार पर निर्भर करता है कि कौन इसे कॉल कर रहा है

इससे मुझे तब तक सिरदर्द होता है जब तक कि मुझे फील्ड एक्सेस और प्रॉपर्टी एक्सेस के बीच का अंतर याद नहीं रहता। अब मैंने अपने सभी एनोटेशन को प्रॉपर्टी ऐक्सेस से फील्ड एक्सेस तक पहुंचा दिया है और यह अब ठीक काम करता है।


हां - मैंने पाया है कि यदि आप संपत्ति के उपयोग का उपयोग करते हैं तो आप वास्तव में अपने सेटर में फ़ील्ड मूल्य निर्धारित करने के अलावा कुछ भी नहीं कर सकते हैं।
एचडीवी

2
+1 गेटर्स / सेटर्स से दूर रहें। मैं Projectlombok.org का उपयोग करता हूं और उन्हें डेवलपर्स से छिपाकर रखता हूं।
१ol:

11

मैं निम्नलिखित कारणों से फ़ील्ड एक्सेस का उपयोग करना पसंद करता हूं:

  1. संपत्ति का उपयोग कर सकते हैं जब बराबरी / hashCode लागू करने और बहुत बुरा कीड़े को जन्म दे सकता सीधे क्षेत्रों को संदर्भित (के रूप में अपने ही टिककर खेल के माध्यम से विरोध)। ऐसा इसलिए है क्योंकि गेटर्स एक्सेस होने पर प्रॉक्सी को केवल इनिशियलाइज़ किया जाता है, और डायरेक्ट-फील्ड एक्सेस बस शून्य रूप से वापस आ जाएगी।

  2. संपत्ति का उपयोग सभी व्याख्या करने की आवश्यकता है उपयोगिता तरीकों (जैसे addChild / removeChild) के रूप में @Transient

  3. फ़ील्ड एक्सेस के साथ हम एक गेट्टर को उजागर न करके @Version फ़ील्ड छिपा सकते हैं। एक गेट्टर भी एक सेटर को जोड़ने के लिए नेतृत्व कर सकता है, और versionफ़ील्ड को कभी भी मैन्युअल रूप से सेट नहीं किया जाना चाहिए (जो बहुत खराब मुद्दों को जन्म दे सकता है)। सभी संस्करण incrementation के माध्यम से शुरू किया जा चाहिए OPTIMISTIC_FORCE_INCREMENT या PESSIMISTIC_FORCE_INCREMENT स्पष्ट ताला।


1. फील्ड एक्सेस रणनीति इसे कैसे रोकती है? यह एक्सेस स्टाइल की परवाह किए बिना, समीपता के साथ एक सामान्य नुकसान है। 2. क्या आप सुनिश्चित हैं, क्या यह केवल उपयोगिता प्राप्त करने वाला होना चाहिए? (लेकिन एक अच्छा तर्क)। 3.version फील्ड के लिए एक्सपोजर एक्सेस अक्सर उन स्थितियों में उपयोगी होता है, जिनमें डीटॉओ का इस्तेमाल अलग-अलग संस्थाओं के बजाय किया जाता है।
ड्रेगन बोजानोविक

1. जब किसी प्रॉक्सी को इनिशियलाइज़ किया जाता है। 2. 100% यकीन है। 3. यह एक वैध बिंदु है।
व्लाद मिहालसी

मेरी अज्ञानता और पाठ व्याख्या की संभावित कमी को क्षमा करें, (मैं कोई मूल अंग्रेजी वक्ता नहीं हूं)। बस स्पष्ट करने के लिए, फ़ील्ड का उपयोग तब होता है जब कोई गेट्टर / सेटर विधियों की आवश्यकता नहीं होती है, इसलिए POJO के लिए, जो समग्र रूप से उपयोग किया जाता है, फ़ील्ड सार्वजनिक हैं? लेकिन आप पहले विषय में कुछ कहते हैं और लिंक किए गए ब्लॉग पोस्ट के विपरीत कहते हैं। मुझे जो समझ में आया वह यह था कि आप समरूपता और फ़ील्ड एक्सेस का उपयोग करते समय बराबर का उपयोग नहीं कर सकते।
MaikoID

फ़ील्ड एक्सेस का अर्थ है कि हाइबरनेट इकाई विशेषताओं को पढ़ने के लिए प्रतिबिंबों के माध्यम से फ़ील्ड का उपयोग करता है। अधिक जानकारी के लिए, हाइबरनेट उपयोगकर्ता गाइड में एक्सेस प्रकार अनुभाग देखें ।
व्लाद मिहाल्सी

7

मुझे लगता है कि संपत्ति की घोषणा करना बेहतर है क्योंकि फ़ील्ड अपडेट करने से सीधे एनकैप्सुलेशन टूट जाता है, तब भी जब आपका ओआरएम ऐसा करता है।

यहाँ एक महान उदाहरण है जहाँ यह आपको जला देगा: आप शायद उसी जगह (या तो फ़ील्ड या गुण) हाइबरनेट सत्यापनकर्ता और दृढ़ता के लिए अपने एनोटेशन चाहते हैं। यदि आप अपने हाइबरनेट सत्यापनकर्ता संचालित सत्यापन का परीक्षण करना चाहते हैं, जो किसी फ़ील्ड पर एनोटेट किए गए हैं, तो आप अपनी इकाई परीक्षण को केवल सत्यापनकर्ता को अलग करने के लिए अपनी इकाई का उपयोग नहीं कर सकते। आउच।


2
इसीलिए आप एक्सेसरों पर सत्यापनकर्ता-एनोटेशन डालते हैं और खेतों पर दृढ़ता-एनोटेशन करते हैं
फिशबोन

6

मेरा मानना ​​है कि प्रॉपर्टी ऐक्सेस बनाम फील्ड एक्सेस आलसी इनिशियलाइजेशन के संबंध में समान रूप से भिन्न है।

2 मूल बीन्स के लिए निम्न मैपिंग पर विचार करें:

<hibernate-mapping package="org.nkl.model" default-access="field">
  <class name="FieldBean" table="FIELD_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

<hibernate-mapping package="org.nkl.model" default-access="property">
  <class name="PropBean" table="PROP_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

और निम्नलिखित इकाई परीक्षण:

@Test
public void testFieldBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    FieldBean fb = new FieldBean("field");
    Long id = (Long) session.save(fb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    fb = (FieldBean) session.load(FieldBean.class, id);
    System.out.println(fb.getId());
    tx.commit();
    session.close();
}

@Test
public void testPropBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    PropBean pb = new PropBean("prop");
    Long id = (Long) session.save(pb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    pb = (PropBean) session.load(PropBean.class, id);
    System.out.println(pb.getId());
    tx.commit();
    session.close();
}

आप आवश्यक चयनों में सूक्ष्म अंतर देखेंगे:

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        FIELD_BEAN
        (message, id) 
    values
        (?, ?)
Hibernate: 
    select
        fieldbean0_.id as id1_0_,
        fieldbean0_.message as message1_0_ 
    from
        FIELD_BEAN fieldbean0_ 
    where
        fieldbean0_.id=?
0
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        PROP_BEAN
        (message, id) 
    values
        (?, ?)
1

यही है, कॉलिंग के fb.getId()लिए एक चयन की आवश्यकता होती है, जबकि pb.getId()ऐसा नहीं है।


यह मजाकिया है! :) लेकिन यह एक कार्यान्वयन-विशिष्ट व्यवहार है, मुझे यकीन है। I
व्लादिमीर Dyuzhev

हां, मुझे लगता है कि यह इस तथ्य के कारण है कि केवल निरंतर वर्ग साधन हैं। हालाँकि यह एक ख़ुशख़बरी है क्योंकि आईडी फ़ील्ड अक्सर एक ऐसा फ़ील्ड होता है जिसका कोई व्यावसायिक मूल्य नहीं होता है और इसे किसी एक्सेसर की आवश्यकता नहीं होती है।
मौरिस पेरी

6

मुझे क्षेत्र-आधारित पहुंच चुनने के लिए सबसे महत्वपूर्ण कारणों को संक्षेप में बताने की कोशिश करते हैं। यदि आप अधिक गहराई से गोता लगाना चाहते हैं, तो कृपया मेरे ब्लॉग पर इस लेख को पढ़ें: जेपीए और हाइबरनेट में पहुंच रणनीतियाँ - कौन सा बेहतर है, क्षेत्र या संपत्ति का उपयोग?

क्षेत्र-आधारित पहुंच बेहतर विकल्प है। इसके 5 कारण इस प्रकार हैं:

कारण 1: अपने कोड की बेहतर पठनीयता

यदि आप फ़ील्ड-आधारित पहुंच का उपयोग करते हैं, तो आप अपनी मैपिंग एनोटेशन के साथ अपनी इकाई विशेषताओं को एनोटेट करते हैं। अपनी कक्षा के शीर्ष पर सभी इकाई विशेषताओं की परिभाषा रखकर, आपको सभी विशेषताओं और उनके मानचित्रण का एक अपेक्षाकृत कॉम्पैक्ट दृश्य मिलता है।

कारण 2: ओट गेट्टर या सेटर विधियां जिन्हें आपके एप्लिकेशन द्वारा नहीं बुलाया जाना चाहिए

क्षेत्र-आधारित पहुंच का एक और लाभ यह है कि आपका दृढ़ता प्रदाता, जैसे, हाइबरनेट या एक्लिप्सलिंक, आपकी इकाई विशेषताओं के गेट्टर और सेटर तरीकों का उपयोग नहीं करता है। इसका मतलब है कि आपको ऐसी कोई विधि प्रदान करने की आवश्यकता नहीं है जिसका उपयोग आपके व्यवसाय कोड द्वारा नहीं किया जाना चाहिए। यह अक्सर प्राथमिक प्राथमिक विशेषताओं या संस्करण कॉलमों के सेटर तरीकों के लिए होता है । आपका दृढ़ता प्रदाता इन विशेषताओं के मूल्यों का प्रबंधन करता है, और आपको उन्हें प्रोग्रामेटिक रूप से सेट नहीं करना चाहिए।

कारण 3: गेट्टर और सेटर विधियों का लचीला कार्यान्वयन

क्योंकि आपका दृढ़ता प्रदाता गेट्टर और सेटर विधियों को कॉल नहीं करता है, वे किसी भी बाहरी आवश्यकताओं को पूरा करने के लिए मजबूर नहीं होते हैं। आप इन तरीकों को अपनी इच्छानुसार लागू कर सकते हैं। यह आपको व्यापार-विशिष्ट सत्यापन नियमों को लागू करने, अतिरिक्त व्यावसायिक तर्क को ट्रिगर करने या इकाई विशेषता को एक अलग डेटा प्रकार में परिवर्तित करने में सक्षम बनाता है।

उदाहरण के लिए, आप एक जावा में एक वैकल्पिक संघ या विशेषता को लपेटने के लिए उपयोग कर सकते हैं Optional

कारण 4: उपयोगिता विधियों को चिह्नित करने की आवश्यकता नहीं है @Transient

क्षेत्र-आधारित पहुंच रणनीति का एक अन्य लाभ यह है कि आपको अपनी उपयोगिता विधियों के साथ टिप्पणी करने की आवश्यकता नहीं है @Transient। यह एनोटेशन आपके हठ प्रदाता को बताता है कि एक विधि या विशेषता इकाई की निरंतर स्थिति का हिस्सा नहीं है। और क्योंकि फील्ड-प्रकार की पहुंच के साथ लगातार स्थिति आपकी इकाई की विशेषताओं द्वारा परिभाषित हो जाती है, आपका जेपीए कार्यान्वयन आपकी इकाई के सभी तरीकों की उपेक्षा करता है।

कारण 5: परदे के पीछे से काम करते समय बग से बचें

हाइबरनेट एक-एक संघों के लिए आलसी भ्रूण के लिए परदे के पीछे का उपयोग करता है, ताकि यह इन संघों के आरंभ को नियंत्रित कर सके। यह दृष्टिकोण लगभग सभी स्थितियों में ठीक काम करता है। यदि आप संपत्ति-आधारित पहुंच का उपयोग करते हैं तो यह एक खतरनाक नुकसान का परिचय देता है।

यदि आप गुण-आधारित पहुँच का उपयोग करते हैं, तो हाइबरनेट आपको प्रॉपर ऑब्जेक्ट की विशेषताओं को प्रारंभ करता है जब आप गेट्टर विधि को कॉल करते हैं। यदि आप अपने व्यवसाय कोड में प्रॉक्सी ऑब्जेक्ट का उपयोग करते हैं तो हमेशा ऐसा ही होता है। लेकिन काफी बराबर और हैशकोड कार्यान्वयन सीधे विशेषताओं तक पहुंचते हैं। यदि यह पहली बार है जब आप किसी भी छद्म विशेषताओं का उपयोग कर रहे हैं, तो ये विशेषताएँ अभी भी असंवैधानिक हैं।


3

डिफ़ॉल्ट रूप से, JPA प्रदाता इकाई फ़ील्ड्स के मानों तक पहुँचते हैं और उन फ़ील्ड्स को डेटाबेस कॉलम में इकाई के JavaBean प्रॉपर्टी एक्सेसर (गेट्टर) और म्यूटेटर (सेटर) विधियों का उपयोग करके मैप करते हैं। जैसे, एक इकाई में निजी क्षेत्रों के नाम और प्रकार जेपीए के लिए कोई मायने नहीं रखते। इसके बजाय, JPA केवल नाम और रिटर्न प्रकार के JavaBean प्रॉपर्टी ऐक्सेसर्स को देखता है। आप @javax.persistence.Accessएनोटेशन का उपयोग करके इसे बदल सकते हैं , जो आपको उस पहुंच पद्धति को स्पष्ट रूप से निर्दिष्ट करने में सक्षम बनाता है जिसे जेपीए प्रदाता को नियोजित करना चाहिए।

@Entity
@Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}

AccessType enum के लिए उपलब्ध विकल्प PROPERTY (डिफ़ॉल्ट) और FIELD हैं। PROPERTY के साथ, प्रदाता JavaBean संपत्ति विधियों का उपयोग करके फ़ील्ड मान प्राप्त करता है और सेट करता है। FIELD प्रदाता को प्राप्त करता है और उदाहरण क्षेत्रों का उपयोग करके फ़ील्ड मान सेट करता है। एक सर्वोत्तम अभ्यास के रूप में, आपको केवल डिफ़ॉल्ट रूप से चिपके रहना चाहिए और JavaBean गुणों का उपयोग करना चाहिए जब तक कि आपके पास अन्यथा करने के लिए एक सम्मोहक कारण न हो।

आप इन संपत्ति एनोटेशन को निजी क्षेत्रों या सार्वजनिक एक्सेसर विधियों पर डाल सकते हैं। यदि आप AccessType.PROPERTYजावा बीन एक्सेसर्स के बजाय निजी फ़ील्ड्स का उपयोग (डिफॉल्ट) करते हैं और एनोटेट करते हैं, तो फ़ील्ड नामों को JavaBean संपत्ति के नामों से मेल खाना चाहिए। हालाँकि, अगर आप JavaBean एक्सेसर्स एनोटेट करते हैं तो नामों का मिलान नहीं होता है। इसी तरह, यदि आप AccessType.FIELDखेतों के बजाय JavaBean एक्सेसर्स का उपयोग और एनोटेट करते हैं, तो फ़ील्ड नामों को भी JavaBean प्रॉपर्टी के नामों से मेल खाना चाहिए। इस मामले में, यदि आप खेतों को एनोटेट करते हैं, तो उनका मिलान नहीं होता है। यह सिर्फ सुसंगत होना और इसके लिए AccessType.PROPERTYऔर इसके लिए जावा बीन एक्सेसर्स को एनोटेट करना सबसे अच्छा है AccessType.FIELD

यह महत्वपूर्ण है कि आपको कभी भी एक ही इकाई में जेपीए संपत्ति एनोटेशन और जेपीए फील्ड एनोटेशन को मिश्रण नहीं करना चाहिए। ऐसा करने से अनिर्दिष्ट व्यवहार होता है और त्रुटियों की संभावना होती है।


2

क्या हम अभी तक वहां पर है

यह एक पुरानी प्रस्तुति है, लेकिन रॉड का सुझाव है कि संपत्ति के उपयोग पर एनोटेशन एनीमिक डोमेन मॉडल को प्रोत्साहित करता है और एनोटेट करने का "डिफ़ॉल्ट" तरीका नहीं होना चाहिए।


2

फ़ील्ड एक्सेस के पक्ष में एक और बिंदु यह है कि अन्यथा आप संग्रह के लिए बसने वालों को भी बेनकाब करने के लिए मजबूर हैं, मेरे लिए, हाइबरनेट द्वारा प्रबंधित ऑब्जेक्ट के लिए लगातार संग्रह उदाहरण को बदलने के रूप में एक बुरा विचार नहीं है, निश्चित रूप से आपके डेटा संगतता को तोड़ देगा।

इसलिए मैं डिफ़ॉल्ट कंस्ट्रक्टर में खाली कार्यान्वयन के लिए संरक्षित क्षेत्रों के रूप में संग्रह करना पसंद करता हूं और केवल अपने गेटर्स को उजागर करता हूं। की तरह फिर, केवल प्रबंधित संचालन clear(), remove(), removeAll()आदि संभव है कि हाइबरनेट परिवर्तन के बारे में पता कर कभी नहीं होगा रहे हैं।


आप कुछ भी उजागर करने के लिए मजबूर नहीं हैं क्योंकि बसने वालों को संरक्षित किया जा सकता है। इसके अलावा जो बसने वाले हैं, वे इंटरफ़ेस का हिस्सा नहीं हैं, भले ही वे सार्वजनिक हों, लेकिन वे आसानी से सुलभ नहीं हैं।
एचडीवी

2

मैं खेतों को पसंद करता हूं, लेकिन मैं एक स्थिति में भाग गया हूं जो मुझे गेटर्स पर एनोटेशन लगाने के लिए मजबूर करता है।

हाइबरनेट जेपीए कार्यान्वयन के साथ, @Embeddedखेतों पर काम करना संभव नहीं लगता है। ताकि गेट पर जाना पड़े। और एक बार जब आप इसे गेट पर रख देते हैं, तो विभिन्न @Columnएनोटेशन को गेटर्स पर भी जाना पड़ता है। (मुझे लगता है कि हाइबरनेट यहां फ़ील्ड और गेटर्स को मिलाना नहीं चाहता है।) और एक बार जब आप @Columnगेटर्स को एक क्लास में डाल रहे होते हैं , तो संभवत: ऐसा करने के लिए समझ में आता है।


2

मैं फील्ड एक्सेसर्स का पक्ष लेता हूं। कोड बहुत क्लीनर है। सभी एनोटेशन को एक वर्ग के एक भाग में रखा जा सकता है और कोड को पढ़ना बहुत आसान है।

मुझे प्रॉपर्टी ऐक्सेसर्स के साथ एक और समस्या देखने को मिली: यदि आपके पास अपनी क्लास में गेटएक्सवाईजेड तरीके हैं जो लगातार संपत्तियों से जुड़े होने के रूप में एनोटेट नहीं हैं, तो हाइबरनेट उन गुणों को प्राप्त करने के लिए एसक्यूएल उत्पन्न करता है, जिसके परिणामस्वरूप कुछ बहुत ही भ्रामक त्रुटि संदेश मिलते हैं। दो घंटे बर्बाद। मैंने यह कोड नहीं लिखा था; मैंने हमेशा अतीत में फ़ील्ड एक्सेसर्स का उपयोग किया है और इस मुद्दे पर कभी नहीं चला।

इस ऐप में उपयोग किए गए हाइबरनेट संस्करण:

<!-- hibernate -->
<hibernate-core.version>3.3.2.GA</hibernate-core.version>
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.1.0.GA</hibernate-commons-annotations.version>
<hibernate-entitymanager.version>3.4.0.GA</hibernate-entitymanager.version>

2

आपको संपत्तियों के माध्यम से पहुंच से अधिक क्षेत्रों तक पहुंच का चयन करना चाहिए। फ़ील्ड के साथ आप भेजे और प्राप्त किए गए डेटा को सीमित कर सकते हैं। गुणों के माध्यम से आप एक मेजबान के रूप में अधिक डेटा भेज सकते हैं, और जी संप्रदायों को सेट कर सकते हैं (जो कारखाना कुल गुणों में से अधिकांश सेट करता है)।




1

हमने इकाई बीन्स बनाए और गेट्टर एनोटेशन का उपयोग किया। समस्या यह है कि हम भाग चुके हैं: कुछ संस्थाओं के पास कुछ संपत्तियों के लिए जटिल नियम हैं जब उन्हें अपडेट किया जा सकता है। समाधान के लिए प्रत्येक सेटर में कुछ व्यावसायिक तर्क थे जो यह निर्धारित करते हैं कि वास्तविक मूल्य बदल गया है या नहीं, यदि ऐसा है, तो परिवर्तन को अनुमति दी जानी चाहिए या नहीं। बेशक, हाइबरनेट हमेशा गुण सेट कर सकता है, इसलिए हमने दो समूहों के साथ समझौता किया। बहुत बदसूरत।

पिछली पोस्टों को पढ़ते हुए, मैं यह भी देखता हूं कि इकाई के अंदर से संपत्तियों को संदर्भित करना संग्रह को लोड न करने के मुद्दों को जन्म दे सकता है।

नीचे की रेखा, मैं भविष्य में खेतों की व्याख्या करने की ओर झुकूंगा।


0

आम तौर पर सेम POJO होते हैं, इसलिए उनके पास वैसे भी एक्सेसर्स होते हैं।

तो सवाल यह नहीं है कि "कौन सा बेहतर है?", लेकिन बस "जब क्षेत्र का उपयोग करना है?"। और जवाब "जब आपको फ़ील्ड के लिए एक सेटर / गेट्टर की आवश्यकता नहीं है!"।


4
समस्या यह है कि आप POJO में फ़ील्ड एक्सेस और प्रॉपर्टी एक्सेस को नहीं मिला सकते हैं - आपको एक चुनना होगा
मार्टिन OConnor

वास्तव में? मैं इसे भूल गया होगा। वैसे भी, मैं हमेशा पीओजेओ को डी एक्सेसर्स का उपयोग करता हूं।
व्लादिमीर Dyuzhev

ध्यान दें कि JPA 2.0 के साथ (जो कि यह प्रश्न पूछे जाने पर आसपास नहीं था) अब आप @AccessType एनोटेशन का उपयोग करके एक्सेस प्रकारों को मिला सकते हैं।
mtpettyp

0

मैं इस बारे में सोच रहा हूं और मैं मेथड एसेसर चुन रहा हूं

क्यों?

क्योंकि फ़ील्ड और मेथोस एक्सेसर समान है लेकिन अगर बाद में मुझे लोड फ़ील्ड में कुछ तर्क की आवश्यकता होती है, तो मैं खेतों में रखे सभी एनोटेशन को स्थानांतरित करता हूं

सादर

Grubhart


0

अपनी कक्षाओं को साफ-सुथरा बनाने के लिए एनोटेशन को क्षेत्र में रखें, फिर @Access (AccessType.PROPERTY) का उपयोग करें


0

दोनों:

EJB3 युक्ति के लिए आवश्यक है कि आप उस तत्व प्रकार पर एनोटेशन की घोषणा करें, जिसे एक्सेस किया जाएगा, अर्थात यदि आप प्रॉपर्टी एक्सेस, फ़ील्ड का उपयोग करते हैं, तो यदि आप फ़ील्ड एक्सेस का उपयोग करते हैं, तो गेट्टर विधि।

https://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/#entity-mapping


0

AccessType.PROPERTY: EJB दृढ़ता कार्यान्वयन JavaBean "सेटर" विधियों के माध्यम से आपकी कक्षा में स्थिति को लोड करेगा, और JavaBean "गेट्टर" विधियों का उपयोग करके अपनी कक्षा से राज्य को पुनः प्राप्त करेगा। यह डिफ़ॉल्ट है।

AccessType.FIELD: राज्य को आपकी कक्षा के क्षेत्रों से सीधे लोड और पुनर्प्राप्त किया जाता है। आपको जावाबीन "गेटर्स" और "सेटर्स" लिखना नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.