كيف يجب أن يساوي hashcode يتم تنفيذها عند استخدام JPA و السبات

StackOverflow https://stackoverflow.com/questions/1638723

سؤال

كيف ينبغي أن نموذج الفئة يساوي hashcode تنفذ في السبات?ما هي المزالق الشائعة?هو تطبيق الافتراضي جيدة بما فيه الكفاية بالنسبة لمعظم الحالات ؟ هل هناك أي معنى لاستخدام الأعمال المفاتيح ؟

يبدو لي أنه من الصعب جدا الحصول على ذلك الحق في العمل في كل حالة ، عندما كسول جلب هوية الجيل, الوكيل, الخ تؤخذ في الاعتبار.

هل كانت مفيدة؟

المحلول

السبات جميل و وصف طويل من عند / كيفية تجاوز equals() / hashCode() في الوثائق

وجوهر ذلك هو أنت فقط بحاجة إلى أن تقلق بشأن ذلك إذا كان الكيان الخاص بك سوف تكون جزءا من Set أو إذا كنت تريد الذهاب إلى فصل / ربط لها الحالات.هذا الأخير ليست شائعة.السابق هو عادة أفضل التعامل معها عن طريق:

  1. مستندة equals() / hashCode() على الأعمال الرئيسية - على سبيل المثال ، مزيج فريد من السمات التي لن تتغير خلال كائن (أو على الأقل الدورة) مدى الحياة.
  2. إذا كان ما سبق هو المستحيل, قاعدة equals() / hashCode() على المفتاح الأساسي إذا كان تعيين وجوه الهوية / System.identityHashCode() خلاف ذلك.على المهم جزء هنا هو أن تحتاج إلى تحميل مجموعة الخاص بك بعد الكيان الجديد تم إضافة إلى أنه مستمرة ؛ وإلا قد ينتهي بك الأمر مع سلوك غريب (مما أدى في نهاية المطاف في أخطاء و / أو البيانات الفساد) لأن الكيان الخاص بك ويمكن تخصيص دلو غير مطابقة الحالي hashCode().

نصائح أخرى

لا أعتقد أن الإجابة المقبولة دقيقة.

للإجابة على السؤال الأصلي:

هو تطبيق الافتراضي جيدة بما فيه الكفاية بالنسبة لمعظم الحالات ؟

الجواب هو نعم ، في معظم الحالات.

تحتاج فقط إلى تجاوز equals() و hashcode() إذا كان الكيان الذي سيتم استخدامه في Set (وهو أمر شائع جدا) و الكيان سوف يكون منفصل من ثم إعادة إرفاق السبات دورات (وهو شائع الاستخدام من السبات).

الجواب المقبول يشير إلى أن الطرق بحاجة إلى أن تنقضها إذا إما الشرط صحيحا.

عندما كيان يتم تحميلها من خلال تحميل كسول, انها لا مثيل قاعدة اكتب لكن هو ديناميكيا الفرعي التي تم إنشاؤها بواسطة javassist ، وبالتالي تحقق على نفس نوع الفئة سوف تفشل لذلك لا تستخدمها:

if (getClass() != that.getClass()) return false;

بدلا من استخدام:

if (!(otherObject instanceof Unit)) return false;

الذي هو أيضا ممارسة جيدة ، كما هو موضح في تنفيذ يساوي في جافا الممارسات.

لنفس السبب ، الوصول مباشرة الحقول قد لا تعمل و العودة فارغة بدلا من القيمة الأساسية ، لذلك لا تستخدم المقارنة على خصائص, ولكن استخدام حاصل ، لأنها قد تؤدي إلى الحمل القيم الأساسية.

أفضل equals/hashCode التنفيذ عند استخدام فريدة من نوعها الأعمال الرئيسية.

الأعمال الرئيسية ينبغي أن تكون متسقة عبر جميع كيان الدولة التحولات (عابر, المرفقة, منفصل, إزالة) ، لهذا لا يمكن الاعتماد على الهوية من أجل المساواة.

وثمة خيار آخر هو التحول إلى استخدام UUID معرفات, تم تعيينها من قبل تطبيق المنطق.بهذه الطريقة, يمكنك استخدام UUID عن equals/hashCode لأن يتم تعيين معرف من قبل الكيان يحصل مسح.

يمكنك حتى استخدام الكيان معرف equals و hashCode, ولكن هذا يتطلب منك العودة دائما نفس hashCode قيمة بحيث يمكنك التأكد من أن الكيان hashCode قيمة متناسقة عبر كافة كيان الدولة التحولات.تحقق من هذا المنصب لمزيد من المعلومات حول هذا الموضوع.

نعم، فمن الصعب. في مشروعي قدم المساواة وشفرة التجزئة على حد سواء تعتمد على هوية الكائن. مشكلة هذا الحل هو أن أيا منهما يعمل إذا لم يتم استمر الكائن بعد، كما يتم إنشاء معرف من قبل قاعدة البيانات. في حالتي هذا مقبولا منذ واستمرت الكائنات في جميع الحالات تقريبا على الفور. عدا ذلك، فإنه يعمل كبيرة وسهلة التنفيذ.

إذا حدث تجاوز equals, تأكد من الوفاء بالعقود:-

  • التماثل
  • عاكسة
  • متعدية
  • ثابت
  • غير فارغة

و تجاوز hashCode, عقد الشركة تعتمد على equals التنفيذ.

جوشوا بلوخ(مصمم جمع الإطار) حث بقوة هذه القواعد التي يجب اتباعها.

  • البند 9:دائما تجاوز hashCode عند تجاوز يساوي

وهناك خطيرة غير مقصودة تأثير عندما كنت لا تتبع هذه العقود.على سبيل المثال List.contains(Object o) قد يعود الخاطئ boolean قيمة العقد العام لم تتحقق.

في وثائق من السبات 5.2 تقول أنك قد لا ترغب في تنفيذ شفرة التجزئة ويساوي على الإطلاق - بالاعتماد على الوضع الخاص بك

HTTPS: // docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#mapping-model-pojo-equalshashcode

وعموما، كائنين تحميلها من نفس الدورة سيكون مساويا إذا كانت تساوي في قاعدة البيانات (بدون تنفيذ شفرة التجزئة ويساوي).

وتتعقد وإذا كنت تستخدم اثنين أو أكثر من الدورات. في هذه الحالة، والمساواة بين كائنين يعتمد على تنفيذ متساوين-طريقتك.

وعلاوة على ذلك، سوف تحصل في ورطة إذا كان لديك متساوين-طريقة هو مقارنة معرفات التي تم إنشاؤها فقط، بينما استمرار كائن لأول مرة. قد لا يكون هناك بعد عندما يتم استدعاء متساوين.

وهناك مادة لطيفة جدا هنا: <لأ href = "https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html" يختلط = " نوفولو "> https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html

ونقلا عن خط المهم من المقال:

<اقتباس فقرة>   

ونحن نوصي متساوين تنفيذ () وشفرة التجزئة () باستخدام المفتاح الأعمال   المساواة. الأعمال المساواة الأساسية يعني أن يساوي () طريقة   يقارن فقط الخصائص التي تشكل مفتاح الأعمال التجارية، والمفتاح الذي   سيحدد سبيل المثال لدينا في العالم الحقيقي (مرشح الطبيعي   مفتاح):

في بعبارات بسيطة

public class Cat {

...
public boolean equals(Object other) {
    //Basic test / class cast
    return this.catId==other.catId;
}

public int hashCode() {
    int result;

    return 3*this.catId; //any primenumber 
}

}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top