2011-09-07 19 views
13

मैं जब JPA2 और EclipseLink का उपयोग कर एक डेटाबेस आवेदन के लिए परीक्षण लेखन एक समस्या मारा जैसा कि मैंने इरादा किया था अतिरिक्त जोड़ा।क्या किसी जेपीए इकाई के आईडी फ़ील्ड को बराबर और हैशकोड में माना जाना चाहिए?</p> <p>मैं एक डेटाबेस के लिए कुछ इकाई जोड़ने के लिए, यह बाद में निकालते हैं और एक उदाहरण है जो मूल्यों मुझे यह बताते हुए कि उम्मीद है करने के लिए यह तुलना करना चाहते हैं:

सबसे पहले मैं की तरह

assertEquals(expResult, dbResult); 

जो विफल रहा है कुछ लिखा था, क्योंकि मैं वास्तव में id क्षेत्र है, जो डेटाबेस से उत्पन्न होता है के मूल्य को नहीं पता कर सकते हैं और इसलिए dbResultexpResult जो मैं new साथ बनाया है और से अलग है मैन्युअल रूप से आबादी।

मैं दो विकल्प देखेंगे:

  • या तो मैं इतना है कि तुलना केवल "वास्तविक मूल्यों" पर आधारित है equals और hashCode से id क्षेत्र को हटा दें। मुझे नहीं पता कि क्या यह डेटाबेस या अन्य जगहों में समस्याएं पैदा करता है, हालांकि।

  • या मैं मैन्युअल रूप से id को छोड़कर प्रत्येक फ़ील्ड को स्पष्ट रूप से जांचने के लिए अपने परीक्षण लिखता हूं।

मुझे क्या करना चाहिए?

उत्तर

14

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

"परीक्षण दृढ़ता संचालन" मोर्चे पर, आप वास्तव में क्या चाहते हैं यह जांचने के लिए है कि फ़ील्ड सहेजे गए थे और सही ढंग से लोड हो गए थे और शायद प्राथमिक कुंजी को सहेजने पर कुछ मूल्य सौंपा गया था। यह शायद बराबर विधि के लिए एक नौकरी नहीं है।

+7

बहुत विवाद मिल सकता है? यह आशावादी है। – digitaljoel

1

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

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

+0

आईडी पर विचार न करने से जुड़े प्रदर्शन और अखंडता की समस्याएं क्या हैं? डेटाबेस आईडी की जांच नहीं करनी चाहिए 'ऑब्जेक्ट # हैशकोड' का उपयोग मेरे 'बराबर' और 'हैशकोड' विधियों में? – soc

+0

आइए कहें कि आपके पास प्रोजेक्ट इकाइयां हैं। आपको अपनी सेवा परत से अद्वितीय परियोजनाओं की एक सूची भेजनी है। अब एक संभावना है कि एक दोषपूर्ण बराबर एक ही रिकॉर्ड के रूप में दो अद्वितीय रिकॉर्ड पर विचार करेगा। आईडी होने से इस समस्या को कम कर देता है। इसके अलावा समाधान स्केलेबल नहीं है, हमें अपने बराबर विधि को अपडेट करना होगा, अगर हम किसी ऑब्जेक्ट को अद्वितीय बनाने के लिए निर्णय लेते हैं। –

+0

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

7

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

7

डेटाबेस पर निर्भर अपने equals में आईडी नहीं बनाया और hashCode कार्यान्वयन उचित नहीं है। आपको समानता की जांच करने और हैशकोड मूल्यों को उत्पन्न करने में अपने वर्गों के वास्तव में अद्वितीय/अर्ध-अद्वितीय विशेषताओं पर भरोसा करना चाहिए। Hibernate documentation का एक व्यापक पृष्ठ है जो इस पर चर्चा करता है, और इसमें तथ्य हर जेपीए प्रदाता के लिए कम या ज्यादा लागू होते हैं।

अपने equals और hashCode कार्यान्वयन में डेटाबेस उत्पन्न मूल्यों से अधिक व्यापार कुंजियों का उपयोग के लिए अंतर्निहित कारण यह है कि जेपीए प्रदाता वास्तव में डेटाबेस में इकाई बने के बाद एक SELECT जारी करना होगा है।

  • तो E1 और E2 वर्ग ई की संस्थाएं हैं (जो का उपयोग कर डेटाबेस आईडी नहीं बनाया समानता की पुष्टि करता है): आप का उपयोग कर डेटाबेस आईडी उत्पन्न वस्तुओं की तुलना है, तो आप एक समानता परीक्षण है कि निम्न परिदृश्यों में विफल रहता है होने खत्म हो जाएगा , तो E1 और E2 बराबर होंगे यदि वे अभी तक डेटाबेस में संग्रहीत नहीं हैं। यह वही नहीं है जो आप चाहते हैं, खासकर यदि E1 और E2 को Set में दृढ़ता से पहले स्टोर करना चाहते हैं। यह खराब है अगर E1 और E2 के गुण अलग-अलग मान रखते हैं; equals कार्यान्वयन Set में दो महत्वपूर्ण भिन्न इकाइयों को जोड़ने से रोक देगा, और hashCode कार्यान्वयन आपको O(n) लुकअप समय देगा जब प्राथमिकता का उपयोग करते हुए HashMap से इकाइयों को देखा जाता है।
  • तो E1 एक प्रबंधित इकाई है कि कायम किया गया है, और E2 एक इकाई है कि कायम नहीं किया गया है, तो समानता परीक्षण समझना होगा कि E1! = परिदृश्य में E2 जहां E1 और E2 के सभी विशेषता मान (सिवाय आईडी के लिए) समान हैं। दोबारा, यह शायद आप नहीं चाहते हैं, विशेष रूप से यदि आप डेटाबेस में डुप्लिकेट इकाइयों से बचना चाहते हैं जो केवल उनके डेटाबेस जेनरेट आईडी में भिन्न है।

equals और hashCode कार्यान्वयन इसलिए व्यापार कुंजी का उपयोग करने के लिए, एक समान व्यवहार प्रदर्शन करने में दोनों कायम और unpersisted संस्थाओं के लिए चाहिए।