सही JPA इकाई बनाएँ [बंद]


422

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

इकाई वर्ग

  • लागू करने योग्य

    कारण: विनिर्देश आपको कहते हैं, लेकिन कुछ जेपीए प्रदाता इसे लागू नहीं करते हैं। JPA प्रदाता के रूप में हाइबरनेट यह लागू नहीं करता है, लेकिन यह ClassCastException के साथ इसके पेट में कहीं गहरे विफल हो सकता है, अगर Serializable कार्यान्वित नहीं किया गया है।

कंस्ट्रक्टर्स

  • इकाई के सभी आवश्यक क्षेत्रों के साथ एक निर्माता बनाएँ

    कारण: एक कंस्ट्रक्टर को हमेशा एक बने हुए अवस्था में छोड़ना चाहिए।

  • इस कंस्ट्रक्टर के अलावा: एक पैकेज निजी डिफ़ॉल्ट कंस्ट्रक्टर है

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

फील्ड्स / गुण

  • जरूरत पड़ने पर सामान्य और संपत्ति के उपयोग में फील्ड एक्सेस का उपयोग करें

    कारण: यह संभवतः सबसे अधिक विवादित मुद्दा है क्योंकि एक या दूसरे के लिए कोई स्पष्ट और ठोस तर्क नहीं हैं (संपत्ति का उपयोग बनाम फ़ील्ड एक्सेस); हालाँकि, फ़ील्ड का उपयोग स्पष्ट कोड, बेहतर एनकैप्सुलेशन और अपरिवर्तनीय क्षेत्रों के लिए बसने की आवश्यकता के कारण सामान्य पसंदीदा नहीं लगता है

  • ओमिट अपरिवर्तनीय क्षेत्रों के लिए बसता है (एक्सेस प्रकार फ़ील्ड के लिए आवश्यक नहीं)

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

बराबर है / hashCode

  • यदि यह आईडी केवल इकाई को बनाए रखने के समय सेट की गई हो तो कभी भी उत्पन्न आईडी का उपयोग न करें
  • वरीयता द्वारा: एक अद्वितीय व्यवसाय कुंजी बनाने के लिए अपरिवर्तनीय मूल्यों का उपयोग करें और समानता का परीक्षण करने के लिए इसका उपयोग करें
  • यदि कोई विशिष्ट व्यवसाय कुंजी उपलब्ध नहीं है, तो एक गैर-क्षणिक UUID का उपयोग करें, जो तब बनाया जाता है जब इकाई आरंभ होती है; देखें इस महान लेख और जानकारी के लिए।
  • संबंधित संस्थाओं (ManyToOne) को कभी न देखें; यदि इस संस्था (एक मूल इकाई की तरह) को बिजनेस की का हिस्सा बनना है तो केवल आईडी की तुलना करें। जब तक आप प्रॉपर्टी ऐक्सेस टाइप का उपयोग कर रहे हों, तब तक प्रॉक्सी पर कॉलिंग गेटआईड () को लोडिंग इकाई को ट्रिगर नहीं करेगा ।

उदाहरण इकाई

@Entity
@Table(name = "ROOM")
public class Room implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    @Column(name = "room_id")
    private Integer id;

    @Column(name = "number") 
    private String number; //immutable

    @Column(name = "capacity")
    private Integer capacity;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "building_id")
    private Building building; //immutable

    Room() {
        // default constructor
    }

    public Room(Building building, String number) {
        // constructor with required field
        notNull(building, "Method called with null parameter (application)");
        notNull(number, "Method called with null parameter (name)");

        this.building = building;
        this.number = number;
    }

    @Override
    public boolean equals(final Object otherObj) {
        if ((otherObj == null) || !(otherObj instanceof Room)) {
            return false;
        }
        // a room can be uniquely identified by it's number and the building it belongs to; normally I would use a UUID in any case but this is just to illustrate the usage of getId()
        final Room other = (Room) otherObj;
        return new EqualsBuilder().append(getNumber(), other.getNumber())
                .append(getBuilding().getId(), other.getBuilding().getId())
                .isEquals();
        //this assumes that Building.id is annotated with @Access(value = AccessType.PROPERTY) 
    }

    public Building getBuilding() {
        return building;
    }


    public Integer getId() {
        return id;
    }

    public String getNumber() {
        return number;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(getNumber()).append(getBuilding().getId()).toHashCode();
    }

    public void setCapacity(Integer capacity) {
        this.capacity = capacity;
    }

    //no setters for number, building nor id

}

इस सूची में जोड़ने के अन्य सुझाव स्वागत से अधिक हैं ...

अपडेट करें

इस लेख को पढ़ने के बाद से मैंने eq / hC को लागू करने के अपने तरीके को अनुकूलित किया है:

  • यदि कोई अपरिवर्तनीय सरल व्यवसाय कुंजी उपलब्ध है: इसका उपयोग करें
  • अन्य सभी मामलों में: एक uuid का उपयोग करें

6
यह एक सवाल नहीं है, यह एक सूची के लिए एक अनुरोध के साथ समीक्षा के लिए अनुरोध है। इसके अलावा, यह बहुत खुला समाप्त और अस्पष्ट है, या अलग तरह से रखा गया है: क्या एक जेपीए इकाई सही है या नहीं, यह इस बात पर निर्भर करता है कि इसका उपयोग किसके लिए किया जा रहा है। क्या हमें एक इकाई के सभी संभावित उपयोगों में एक इकाई की आवश्यकता हो सकती है सभी चीजों को सूचीबद्ध करना चाहिए?
मेरिटॉन

मुझे पता है कि यह स्पष्ट कट प्रश्न नहीं है जिसके लिए मैं माफी मांगता हूं। यह वास्तव में सूची के लिए अनुरोध नहीं है, बल्कि टिप्पणियों / टिप्पणियों के लिए एक अनुरोध है, हालांकि अन्य सुझावों का स्वागत है। जेपीए इकाई के संभावित उपयोगों के बारे में विस्तार से बेझिझक कहिए।
स्टिजेन ज्यूकेन्स

मैं यह भी चाहूंगा कि खेतों को final(आपके बसने की ललक को देखते हुए, मुझे लगता है कि आप भी ऐसा करेंगे)।
श्रीधर सरनोबत

यह कोशिश करनी होगी, लेकिन मुझे नहीं लगता कि अंतिम काम करेगा क्योंकि हाइबरनेट को अभी भी उन गुणों पर मूल्यों को सेट करने में सक्षम होने की आवश्यकता है।
स्टिजेन ज्यूकेन्स

कहाँ notNullसे आता है?
ब्रूनो

जवाबों:


73

मैं कई प्रमुख बिंदुओं का जवाब देने की कोशिश करूंगा: यह लंबे हाइबरनेट / दृढ़ता के अनुभव से है जिसमें कई प्रमुख अनुप्रयोग शामिल हैं।

इकाई वर्ग: धारावाहिक लागू करें?

कुंजी को सीरियल को लागू करने की आवश्यकता है। सामग्री जो HttpSession में जाने वाली है, या RPC / Java EE द्वारा वायर पर भेजी जा सकती है, को Serializable को लागू करने की आवश्यकता है। अन्य सामान: इतना नहीं। अपना समय इस बात पर व्यतीत करें कि क्या महत्वपूर्ण है।

कंस्ट्रक्टर्स: इकाई के सभी आवश्यक क्षेत्रों के साथ एक कंस्ट्रक्टर बनाएं?

आवेदन तर्क के लिए कंस्ट्रक्टर (ओं) के पास केवल कुछ महत्वपूर्ण "विदेशी कुंजी" या "प्रकार / प्रकार" फ़ील्ड होनी चाहिए जो हमेशा इकाई बनाते समय ज्ञात होंगी। बाकी को सेटर विधियों को कॉल करके सेट किया जाना चाहिए - यही वे के लिए हैं।

कंस्ट्रक्टरों में बहुत सारे क्षेत्र डालने से बचें। कंस्ट्रक्टर्स सुविधाजनक होना चाहिए, और ऑब्जेक्ट को बुनियादी पवित्रता देना चाहिए। नाम, प्रकार और / या माता-पिता सभी आमतौर पर उपयोगी होते हैं।

OTOH यदि अनुप्रयोग नियम (आज) के लिए ग्राहक के पास पता होना आवश्यक है, तो उसे एक सेटर पर छोड़ दें। यह एक "कमजोर शासन" का एक उदाहरण है। हो सकता है कि अगले सप्ताह, आप Enter Details स्क्रीन पर जाने से पहले एक ग्राहक ऑब्जेक्ट बनाना चाहते हैं? अपने आप को यात्रा न करें, अज्ञात, अपूर्ण या "आंशिक रूप से दर्ज" डेटा के लिए संभावना छोड़ दें।

कंस्ट्रक्टर्स: पैकेज, प्राइवेट डिफॉल्ट कंस्ट्रक्टर?

हां, लेकिन पैकेज निजी के बजाय 'संरक्षित' का उपयोग करें। जब आवश्यक इंटर्न दिखाई नहीं देते हैं तो सबक्लासिंग सामान एक वास्तविक दर्द होता है।

फील्ड्स / गुण

हाइबरनेट के लिए 'प्रॉपर्टी' फील्ड एक्सेस का उपयोग करें, और उदाहरण के बाहर से। उदाहरण के भीतर, सीधे खेतों का उपयोग करें। कारण: मानक प्रतिबिंब, हाइबरनेट के लिए सबसे सरल और सबसे बुनियादी विधि, काम करने की अनुमति देता है।

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

नोट: जब एक बराबर () फ़ंक्शन लिखते हैं, तो 'अन्य' उदाहरण पर मान के लिए गेटर्स का उपयोग करें! अन्यथा, आप प्रॉक्सी इंस्टेंसेस पर अनइंस्टॉलिज्ड / खाली फील्ड को हिट करेंगे।

संरक्षित (हाइबरनेट) प्रदर्शन के लिए बेहतर है?

संभावना नहीं है।

बराबर है / हैशकोड?

यह संस्थाओं के साथ काम करने के लिए प्रासंगिक है, इससे पहले कि वे बच गए हैं - जो एक कांटेदार मुद्दा है। अपरिवर्तनीय मूल्यों पर मारना / तुलना करना? अधिकांश व्यावसायिक अनुप्रयोगों में, कोई भी नहीं हैं।

एक ग्राहक पता बदल सकता है, अपने व्यवसाय का नाम बदल सकता है, आदि-आदि आम नहीं है, लेकिन ऐसा होता है। जब डेटा सही ढंग से दर्ज नहीं किया गया था, तो सुधार करने के लिए भी संभव हो सकता है।

कुछ चीजें जो सामान्य रूप से अपरिवर्तनीय रखी जाती हैं, वे हैं पेरेंटिंग और शायद टाइप / काइंड - आमतौर पर उपयोगकर्ता इन को बदलने के बजाय रिकॉर्ड को फिर से बनाता है। लेकिन ये विशिष्ट रूप से इकाई की पहचान नहीं करते हैं!

इसलिए, लंबा और छोटा, दावा किया गया "अपरिवर्तनीय" डेटा वास्तव में नहीं है। प्राथमिक कुंजी / आईडी फ़ील्ड सटीक उद्देश्य के लिए उत्पन्न होते हैं, इस तरह की गारंटी स्थिरता और अपरिवर्तनीयता प्रदान करते हैं।

जब आप ए / हैश से "असमान रूप से परिवर्तित फ़ील्ड्स", या बी) के साथ काम कर रहे हों, तो आपको A से "परिवर्तित / बाउंड डेटा" के साथ काम करते समय ए और हैशिंग और रिक्वेस्ट-प्रोसेसिंग कार्य चरणों के लिए अपनी आवश्यकता की योजना बनाने और विचार करने की आवश्यकता है। बिना डेटा के ", यदि आप ID पर हैश की तुलना करते हैं।

बराबर / हैशकोड - यदि कोई अनोखी व्यावसायिक कुंजी उपलब्ध नहीं है, तो एक गैर-क्षणिक UUID का उपयोग करें, जो तब बनाया जाता है जब इकाई को आरंभीकृत किया जाता है

हां, आवश्यकता पड़ने पर यह एक अच्छी रणनीति है। ध्यान रखें कि यूयूआईडी स्वतंत्र नहीं हैं, हालांकि प्रदर्शन-वार - और क्लस्टरिंग चीजों को जटिल करता है।

समान / हैशकोड - संबंधित संस्थाओं को कभी नहीं देखें

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

अच्छी सलाह की तरह लगता है।

उम्मीद है की यह मदद करेगा!


2
पुन: रचनाकारों, मैं अक्सर शून्य arg केवल (यानी कोई नहीं) देखते हैं और कॉलिंग कोड में बसने वालों की एक लंबी लंबी सूची है जो मुझे थोड़ा गड़बड़ लगता है। वहाँ वास्तव में किसी भी निर्माण के साथ कोई समस्या है जो आपकी जरूरत के अनुरूप है, जिससे कॉलिंग कोड अधिक रसीला हो जाता है?
तूफान

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

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

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

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

144

जेपीए 2.0 विशिष्टता कहा गया है कि:

  • एंटिटी क्लास में एक नो-आर्ग कंस्ट्रक्टर होना चाहिए। इसमें अन्य कंस्ट्रक्टर भी हो सकते हैं। नो-आर्ग कंस्ट्रक्टर को सार्वजनिक या संरक्षित होना चाहिए।
  • एंटिटी क्लास को टॉप-लेवल क्लास होना चाहिए। एक एनम या इंटरफ़ेस को एक इकाई के रूप में निर्दिष्ट नहीं किया जाना चाहिए।
  • इकाई वर्ग अंतिम नहीं होना चाहिए। इकाई वर्ग का कोई भी तरीका या लगातार उदाहरण चर अंतिम नहीं हो सकता है।
  • यदि एक इकाई उदाहरण को एक अलग वस्तु के रूप में मूल्य द्वारा पारित किया जाना है (जैसे, एक दूरस्थ इंटरफ़ेस के माध्यम से), तो इकाई वर्ग को सीरियल इंटरफ़ेस लागू करना होगा।
  • अमूर्त और ठोस दोनों वर्ग अस्तित्व हो सकते हैं। इकाईयां गैर-इकाई वर्ग के साथ-साथ इकाई वर्ग का विस्तार कर सकती हैं, और गैर-इकाई वर्ग इकाई वर्ग का विस्तार कर सकते हैं।

विनिर्देश में संस्थाओं के लिए समान और हैशकोड विधियों के कार्यान्वयन के बारे में कोई आवश्यकता नहीं है, केवल प्राथमिक कुंजी वर्गों और मानचित्र कुंजियों के लिए जहां तक ​​मैं जानता हूं।


13
सच है, बराबरी, हैशकोड, ... एक जेपीए आवश्यकता नहीं हैं, लेकिन निश्चित रूप से अनुशंसित हैं और अच्छे अभ्यास माने जाते हैं।
स्टिजेन ज्यूकेन्स

6
@ TheStijn खैर, जब तक आप समानता के लिए अलग-अलग संस्थाओं की तुलना करने की योजना नहीं बनाते हैं, यह संभवतः अनावश्यक है। हर बार आपके द्वारा मांगे जाने पर इकाई प्रबंधक को किसी दिए गए निकाय के उसी उदाहरण को वापस करने की गारंटी दी जाती है। इसलिए, आप प्रबंधित संस्थाओं के लिए पहचान तुलना के साथ ठीक कर सकते हैं, जहां तक ​​मैं समझता हूं। क्या आप उन परिदृश्यों के बारे में थोड़ा और विस्तार से बता सकते हैं जिनमें आप इस पर विचार करेंगे?
एडविन डेलोरजो

2
मैं हमेशा बराबर / हैशकोड का सही क्रियान्वयन करने का प्रयास करता हूं। JPA के लिए आवश्यक नहीं है, लेकिन मैं इसे जब संस्थाओं के लिए या समुच्चय में जोड़ा जाता है तो एक अच्छा अभ्यास मानता हूं। आप केवल समान लागू करने का निर्णय ले सकते हैं जब संस्थाओं को सेट में जोड़ा जाएगा लेकिन क्या आप हमेशा पहले से जानते हैं?
स्टिजेन ज्यूकेन्स

10
@ TheStijn जेपीए प्रदाता यह सुनिश्चित करेगा कि किसी भी समय संदर्भ में किसी दिए गए निकाय का केवल एक उदाहरण है, इसलिए यहां तक ​​कि आपके सेट भी समान / हैकोड को लागू किए बिना सुरक्षित हैं, बशर्ते कि आप केवल प्रबंधित संस्थाओं का उपयोग करें। संस्थाओं के लिए इन विधियों को लागू करना कठिनाइयों से मुक्त नहीं है, उदाहरण के लिए, इस विषय के बारे में हाइबरनेट अनुच्छेद पर एक नज़र डालें । मेरी बात, यदि आप केवल प्रबंधित संस्थाओं के साथ काम करते हैं, तो आप उनके बिना बेहतर हैं, अन्यथा बहुत सावधानीपूर्वक कार्यान्वयन प्रदान करते हैं।
एडविन डेलोरजो

2
@ TheStijn यह अच्छा मिश्रित परिदृश्य है। यह ईक / एचसी को लागू करने की आवश्यकता को सही ठहराता है जैसा कि आपने शुरू में सुझाव दिया था क्योंकि एक बार जब संस्थाएं दृढ़ता परत की सुरक्षा को छोड़ देती हैं तो आप अब जेपीए मानक द्वारा लागू किए गए नियमों पर भरोसा नहीं कर सकते हैं। हमारे मामले में, डीटीओ पैटर्न को शुरू से ही वास्तुकला में लागू किया गया था। डिजाइन के द्वारा हमारी दृढ़ता एपीआई व्यापार वस्तुओं के साथ बातचीत करने के लिए एक सार्वजनिक तरीका प्रदान नहीं करती है, केवल डीटीओ का उपयोग करके हमारी दृढ़ता परत के साथ बातचीत करने के लिए एक एपीआई।
एडविन डेलोरजो

13

मेरे 2 सेंट के जवाब के अलावा यहाँ हैं:

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

  2. बराबरी / हैशकोड के संदर्भ के साथ: एक द्वि-दिशात्मक संबंध में भाग लेने वाली संस्थाओं के लिए ग्रहण ऑटो-जनरेटेड इक्वल / हैशकोड विधियों का उपयोग करना असंभव है, अन्यथा उनके पास एक परिपत्र संदर्भ होगा, जिसके परिणामस्वरूप स्टैकओवरफ़्लो अपवाद होगा। एक बार जब आप एक द्विदिश संबंध (OneToOne कहते हैं) और ऑटो-जेनरेट इक्वल्स () या हैशकोड () या यहां तक ​​कि स्ट्रींग () करने का प्रयास करते हैं, तो आप इस स्टैकओवरफ्लो अपवाद में फंस जाएंगे।


9

इकाई इंटरफ़ेस

public interface Entity<I> extends Serializable {

/**
 * @return entity identity
 */
I getId();

/**
 * @return HashCode of entity identity
 */
int identityHashCode();

/**
 * @param other
 *            Other entity
 * @return true if identities of entities are equal
 */
boolean identityEquals(Entity<?> other);
}

सभी संस्थाओं के लिए बुनियादी कार्यान्वयन, समान / हाशकोड कार्यान्वयन को सरल बनाता है:

public abstract class AbstractEntity<I> implements Entity<I> {

@Override
public final boolean identityEquals(Entity<?> other) {
    if (getId() == null) {
        return false;
    }
    return getId().equals(other.getId());
}

@Override
public final int identityHashCode() {
    return new HashCodeBuilder().append(this.getId()).toHashCode();
}

@Override
public final int hashCode() {
    return identityHashCode();
}

@Override
public final boolean equals(final Object o) {
    if (this == o) {
        return true;
    }
    if ((o == null) || (getClass() != o.getClass())) {
        return false;
    }

    return identityEquals((Entity<?>) o);
}

@Override
public String toString() {
    return getClass().getSimpleName() + ": " + identity();
    // OR 
    // return ReflectionToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

कक्ष इकाई निहित:

@Entity
@Table(name = "ROOM")
public class Room extends AbstractEntity<Integer> {

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "room_id")
private Integer id;

@Column(name = "number") 
private String number; //immutable

@Column(name = "capacity")
private Integer capacity;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "building_id")
private Building building; //immutable

Room() {
    // default constructor
}

public Room(Building building, String number) {
    // constructor with required field
    notNull(building, "Method called with null parameter (application)");
    notNull(number, "Method called with null parameter (name)");

    this.building = building;
    this.number = number;
}

public Integer getId(){
    return id;
}

public Building getBuilding() {
    return building;
}

public String getNumber() {
    return number;
}


public void setCapacity(Integer capacity) {
    this.capacity = capacity;
}

//no setters for number, building nor id
}

मुझे JPA संस्थाओं के प्रत्येक मामले में व्यावसायिक क्षेत्रों के आधार पर संस्थाओं की समानता की तुलना करने का एक बिंदु नहीं दिखता है। यह एक मामला हो सकता है अगर इन JPA संस्थाओं को डोमेन-चालित मूल्य के बजाय डोमेन-चालित मान के रूप में माना जाता है, (जो इन कोड उदाहरणों के लिए हैं)।


4
यद्यपि बायलर प्लेट कोड को निकालने के लिए पैरेंट एंटिटी क्लास का उपयोग करना एक अच्छा तरीका है, लेकिन डीबी डिफाइंड आईडी का उपयोग करने के लिए यह एक अच्छा विचार नहीं है। आपके मामले में 2 नई संस्थाओं की तुलना करना भी एक NPE फेंक देगा। यहां तक ​​कि अगर आप इसे शून्य सुरक्षित बनाते हैं, तो 2 नई इकाइयां हमेशा समान रहेंगी, जब तक कि वे बरकरार न हों। Eq / hC अपरिवर्तनीय होना चाहिए।
स्टिजर्न जुकेंस

2
बराबरी () एनपीई को नहीं फेंकेंगे क्योंकि यह जांच है कि डीबी आईडी शून्य है या नहीं और यदि डीबी आईडी शून्य है, तो समानता झूठी होगी।
अहानमन

3
वास्तव में, मैं यह नहीं देखता कि मैंने कैसे याद किया कि कोड शून्य-सुरक्षित है। लेकिन IMO आईडी का उपयोग करना अभी भी बुरा व्यवहार है। तर्क: onjava.com/pub/a/onjava/2006/09/13/…
Stijn Geukens

वॉन वर्नोन की किताब 'इंप्लीमेंटिंग डीडीडी' में, यह तर्क दिया गया है कि यदि आप "प्रारंभिक पीके पीढ़ी" का उपयोग करते हैं तो आप समान के लिए आईडी का उपयोग कर सकते हैं (पहले एक पीढ़ी उत्पन्न करें और इसे डेटाबेस के निर्माण के विपरीत इकाई के निर्माता में पास करें। आईडी जब आप संस्था को जारी रखते हैं।)
विम डेब्लॉवे

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