জেপিএ এবং হাইবারনেট ব্যবহার করার সময় কীভাবে সমান এবং হ্যাশকোড প্রয়োগ করা উচিত


103

হাইবারনেটে মডেল শ্রেণির সমান এবং হ্যাশকোড কীভাবে প্রয়োগ করা উচিত? সাধারণ সমস্যাগুলি কী কী? ডিফল্ট বাস্তবায়ন বেশিরভাগ ক্ষেত্রেই যথেষ্ট ভাল? ব্যবসায়ের কীগুলি ব্যবহার করার কোনও ধারণা আছে?

আমার কাছে মনে হয়েছে যে অলস আনার সময়, আইডি জেনারেশন, প্রক্সি ইত্যাদি বিবেচনায় নেওয়া হলে প্রতিটি পরিস্থিতিতে কাজ করা সঠিক হওয়া খুব কঠিন।


আরও দেখুন stackoverflow.com/a/39827962/548473 (বসন্ত-ডেটা-jpa বাস্তবায়ন)
গ্রেগরি Kislin

উত্তর:


74

হাইবারনেট যখন / ওভাররাইড করতে কিভাবে একটি চমৎকার এবং দীর্ঘ বিবরণ নেই equals()/ hashCode()ডকুমেন্টেশন

এটির মূল বক্তব্য হ'ল আপনার সত্তা কোনও অংশ হয়ে উঠবে Setবা আপনি যদি এর উদাহরণগুলিকে বিচ্ছিন্ন / সংযুক্ত করতে চলেছেন তবে আপনাকে কেবল এটির জন্য উদ্বেগের প্রয়োজন । দ্বিতীয়টি সাধারণ নয়। প্রাক্তনটি সাধারণত এর মাধ্যমে সর্বোত্তমভাবে পরিচালিত হয়:

  1. বিজনিং equals()/ hashCode()ব্যবসায়ের কী - যেমন বৈশিষ্ট্যের একটি অনন্য সংমিশ্রণ যা অবজেক্টের (বা, কমপক্ষে, সেশন) আজীবন চলাকালীন পরিবর্তিত হয় না।
  2. যদি উপরোক্ত অসম্ভব, বেস হল equals()/ hashCode()প্রাথমিক কী করতে চান তবে এটা সেট এবং বস্তুর পরিচয় / System.identityHashCode()অন্যথায়। এখানে গুরুত্বপূর্ণ অংশটি হ'ল নতুন সত্তা যুক্ত হওয়ার পরেও এটির পরে আপনার সেটটি পুনরায় লোড করা দরকার ; অন্যথায় আপনি অদ্ভুত আচরণের সাথে পরিণতি পেতে পারেন (শেষ পর্যন্ত ত্রুটি এবং / বা ডেটা দুর্নীতির ফলস্বরূপ) কারণ আপনার সত্তা কোনও বালতিতে বরাদ্দ করা যেতে পারে যা তার বর্তমানের সাথে মেলে না hashCode()

1
যখন আপনি "পুনরায় লোড করুন" @ ChssPly76 বলতে চাচ্ছেন আপনি কি করছেন refresh()? আপনার সত্তা, যা Setচুক্তিটি মানছে তা ভুল বালতিতে শেষ হবে (ধরে নিলে আপনার যথেষ্ট ভাল হ্যাশকোড বাস্তবায়ন হয়েছে)।
অনুচিহ্নবিহীন

4
সংগ্রহটি রিফ্রেশ করুন বা পুরো (মালিক) সত্তা পুনরায় লোড করুন, হ্যাঁ। যতক্ষণ না ভুল বালতি যায়: ক) আপনি সেট করতে নতুন সত্তা যুক্ত করেছেন, এটির আইডি এখনও সেট করা হয়নি তাই আপনি পরিচয়্যাশকোড ব্যবহার করছেন যা আপনার সত্তাকে বালতি # 1 এ রাখে। খ) আপনার সত্তা (সেট মধ্যে) অবিচ্ছিন্ন, এটি এখন একটি আইডি আছে এবং সুতরাং আপনি এই আইডি উপর ভিত্তি করে হ্যাশকোড () ব্যবহার করছেন। এটি উপরের থেকে পৃথক এবং আপনার সত্তা বালতি # 2 এ স্থাপন করত । এখন ধরে নেওয়া, আপনি অন্য কোথাও এই সত্তার একটি রেফারেন্স রেখেছেন, কল করার চেষ্টা করুন Set.contains(entity)এবং আপনি ফিরে পাবেন false। একই পান () / করা () জন্য / etc জন্য যায় ...
ChssPly76

জ্ঞান করে তোলে কিন্তু identityHashCode নিজেকে ব্যবহৃত যদিও আমি দেখতে এটা তাদের ResultTransformers মত হাইবারনেট উৎস এ আর কখনও ব্যবহৃত
অ sequitor

1
হাইবারনেট ব্যবহার করার সময়, আপনি এই সমস্যার মধ্যেও চলে যেতে পারেন , যার এখনও আমি কোনও সমাধান পাইনি।
জিওভানি বোট্টা

@ CHssPly76 ব্যবসায়ের নিয়মের কারণে যা নির্ধারিত হয় যে দুটি বস্তু সমান কিনা আমাকে আমার সমান / হ্যাশকোড পদ্ধতিগুলি এমন বৈশিষ্ট্যের উপর ভিত্তি করে গড়ে তুলতে হবে যা কোনও বস্তুর জীবদ্দশায় পরিবর্তন হতে পারে। আসলেই কি বড় ব্যাপার? যদি তাই হয় কিভাবে আমি এটি কাছাকাছি পেতে পারি?
ubiquibacon

39

আমি মনে করি না যে গৃহীত উত্তরটি সঠিক।

মূল প্রশ্নের উত্তর দিতে:

ডিফল্ট বাস্তবায়ন বেশিরভাগ ক্ষেত্রেই যথেষ্ট ভাল?

উত্তর হ্যাঁ, বেশিরভাগ ক্ষেত্রেই এটি হয়।

আপনাকে কেবল ওভাররাইড করতে হবে equals()এবং hashcode()যদি সত্তাটি কোনও Set(যা খুব সাধারণ) এবং এন্ডে ব্যবহৃত হয় সত্তাটি হাইবারনেট সেশনগুলি থেকে আলাদা করা হবে এবং পরবর্তীকালে পুনরায় সংযুক্ত করা হবে (যা হাইবারনেটের অস্বাভাবিক ব্যবহার)।

গৃহীত উত্তরটি ইঙ্গিত দেয় যে উভয় শর্ত সত্য হলে পদ্ধতিগুলি ওভাররাইড করা দরকার ।


এটি আমার পর্যবেক্ষণের সাথে সারিবদ্ধ, কেন তা খুঁজে বের করার সময় ।
ভ্লাসটিমিল ওভেক

"আপনাকে কেবলমাত্র সমান () এবং হ্যাশকোড () ওভাররাইড করতে হবে যদি সত্তাটি কোনও সেটে ব্যবহৃত হবে" সম্পূর্ণরূপে যথেষ্ট যদি কিছু ক্ষেত্র কোনও বস্তু সনাক্ত করে এবং তাই আপনি সনাক্ত করার জন্য অবজেক্ট.ইকুয়ালস () এর উপর নির্ভর করতে চান না অবজেক্ট।
ডেভিডএক্সএক্সএক্সএক্স

17

সেরা equals/ hashCodeবাস্তবায়ন হ'ল আপনি যখন একটি অনন্য ব্যবসায়ের কী ব্যবহার করেন ।

ব্যবসায়ের কীটি সমস্ত সত্তার রাষ্ট্রীয় রূপান্তরগুলিতে (ক্ষণস্থায়ী, সংযুক্ত, বিচ্ছিন্ন, অপসারণ) জুড়ে সামঞ্জস্যপূর্ণ হওয়া উচিত , এজন্যই আপনি সাম্যের জন্য আইডির উপর নির্ভর করতে পারবেন না।

আর একটি বিকল্প হ'ল অ্যাপ্লিকেশন যুক্তি দ্বারা নির্ধারিত ইউআইডি সনাক্তকারী ব্যবহার করে স্যুইচ করা । এইভাবে, আপনি equals/ জন্য ইউআইডি ব্যবহার করতে পারেন hashCodeকারণ সত্তাটি ফ্লাশ হওয়ার আগে আইডি নির্ধারিত হয়।

এমনকি আপনি জন্য সত্তা সনাক্তকারী ব্যবহার করতে পারেন equalsএবং hashCode, কিন্তু যে সবসময় একই আসতে করতে হবে hashCode, যাতে মান আপনি কি নিশ্চিত যে সত্তা হ্যাশকোড মান সব সত্তা রাষ্ট্র ট্রানজিশন জুড়ে সামঞ্জস্যপূর্ণ ভুলবেন না। পরীক্ষা করে দেখুন এই বিষয়ে আরো জন্য পোস্টটি


ইউইড পদ্ধতির জন্য +1। এটিকে একটি করে ফেলুন BaseEntityএবং কখনও কখনও সেই সমস্যাটি নিয়ে ভাবেন না। এটি ডিবি দিকে কিছুটা জায়গা লাগে তবে সেই দামটি আপনি আরামের জন্য আরও ভাল মূল্য দিতে পারেন :)
মার্টিন ফ্রে

12

যখন কোনও সত্ত্বা অলস লোডিংয়ের মাধ্যমে লোড করা হয়, এটি বেস টাইপের উদাহরণ নয়, তবে জাভাসিস্ট দ্বারা তৈরি করা একটি গতিশীলভাবে তৈরি সাব টাইপ, সুতরাং একই শ্রেণীর ধরণের একটি চেক ব্যর্থ হবে, সুতরাং ব্যবহার করবেন না:

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

পরিবর্তে ব্যবহার করুন:

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

যা একটি ভাল অনুশীলন, যেমন জাভা অনুশীলনে সমান বাস্তবায়ন সম্পর্কে ব্যাখ্যা করা হয়েছে

একই কারণে, সরাসরি ক্ষেত্রগুলিতে অ্যাক্সেস করা, অন্তর্নিহিত মানের পরিবর্তে, কাজ করে এবং নাল ফিরে নাও আসতে পারে, সুতরাং বৈশিষ্ট্যের সাথে তুলনা না করে ব্যবহারকারীর ব্যবহার করুন, কারণ তারা অন্তর্নিহিত মানগুলি লোড করার জন্য ট্রিগার করতে পারে।


1
আপনি যদি কংক্রিটের ক্লাসগুলির সাথে তুলনা করে যা এটি আমার পরিস্থিতিতে কাজ করে না এটি কাজ করে work আমি সুপার ক্লাস বস্তু, যে ক্ষেত্রে এই কোড আমার জন্য কাজ তুলনা করা হয়েছে:। Obj1.getClass () isInstance (obj2)
বাচ্চা

6

হ্যাঁ, এটা শক্ত। আমার প্রকল্পের সমান এবং হ্যাশকোড উভয়ই অবজেক্টের আইডির উপর নির্ভর করে। এই সমাধানটির সমস্যাটি হ'ল এই আইডিটি ডেটাবেস দ্বারা উত্পন্ন হওয়ায় অবজেক্টটি এখনও অব্যাহত না রাখলে উভয়ই কাজ করে না। আমার ক্ষেত্রে এটি সহনীয় কারণ প্রায় সব ক্ষেত্রেই অবজেক্টগুলি এখনই টিকিয়ে রাখা হয়। তা ছাড়া, এটি দুর্দান্ত কাজ করে এবং কার্যকর করা সহজ।


আমার মনে হয় আমরা যা করেছি তা হ'ল আইডিটি তৈরি করা হয়নি এমন ক্ষেত্রে অবজেক্টের পরিচয় ব্যবহার করা
ক্যাথি ভ্যান স্টোন

2
এখানে সমস্যাটি হ'ল আপনি যদি অবজেক্টটি অব্যাহত রাখেন তবে আপনার হ্যাশকোড পরিবর্তন হয়। যদি বস্তুটি ইতিমধ্যে হ্যাশ ভিত্তিক ডেটা কাঠামোর অংশ হয় তবে এটির জন্য ক্ষতিকারক ফলাফলগুলি হতে পারে। সুতরাং, যদি আপনি অবজেক্ট আইডেন্টিটিটি ব্যবহার করে বাধা বজায় রাখেন তবে অবজেক্ট আইডি ব্যবহার না করা অবধি অবজেক্টটি সম্পূর্ণ মুক্ত না হওয়া পর্যন্ত (বা কোনও হ্যাশ ভিত্তিক স্ট্রাকচার থেকে অবজেক্টটি সরিয়ে ফেলতে হবে, তারপরে আবার যুক্ত করুন)। ব্যক্তিগতভাবে, আমি মনে করি আইডি ব্যবহার না করা ভাল, এবং হ্যাশটিকে অবজেক্টের অপরিবর্তনীয় বৈশিষ্ট্যের ভিত্তিতে রাখা ভাল।
কেভিন দিন

1

হাইবারনেট 5.2 এর ডকুমেন্টেশনে এটি বলেছে আপনি হ্যাশকোড প্রয়োগ করতে চান না এবং আপনার অবস্থার উপর নির্ভর করে মোটেও সমান হন।

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

সাধারণত, একই অধিবেশন থেকে লোড করা দুটি বস্তু সমান হবে যদি তারা ডাটাবেসে সমান হয় (হ্যাশকোড এবং সমতুল্য প্রয়োগ না করে)।

আপনি দুটি বা ততোধিক সেশন ব্যবহার করলে এটি জটিল হয়ে যায়। এই ক্ষেত্রে, দুটি বস্তুর সমতা আপনার সমান-পদ্ধতি প্রয়োগের উপর নির্ভর করে।

তদুপরি, যদি আপনার সমান-পদ্ধতিটি আইডিগুলির সাথে তুলনা করে যা প্রথমবারের জন্য কোনও অবজেক্টকে স্থির রাখার সময় উত্পন্ন হয়। সমান বলা হলেও তারা এখনও সেখানে থাকতে পারে না।


0

এখানে খুব সুন্দর নিবন্ধ রয়েছে: https://docs.jboss.org/hibernate/stable/core.old/references/en/html/persistent-class-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 
}

}

0

যদি আপনার ওভাররাইডের ঘটনা ঘটে থাকে তবে equalsনিশ্চিত হয়ে নিন যে আপনি এর চুক্তিগুলি সম্পাদন করেছেন: -

  • প্রতিসাম্য
  • চিন্তাশীল
  • সকর্মক
  • সঙ্গত
  • কিছুই নয়

ওভাররাইড hashCode, যেমন এটির চুক্তি নির্ভর করেequals বাস্তবায়নের ।

জোশুয়া ব্লচ (সংগ্রহ কাঠামোর ডিজাইনার) এই নিয়মগুলি অনুসরণ করার জন্য দৃ strongly়ভাবে অনুরোধ করেছিলেন।

  • আইটেম 9: আপনি যখন সমান ওভাররাইড করবেন তখন সর্বদা হ্যাশকোডকে ওভাররাইড করুন

আপনি যখন এই চুক্তিগুলি অনুসরণ না করেন তখন মারাত্মক অনিচ্ছাকৃত প্রভাব থাকে। উদাহরণস্বরূপ সাধারণ চুক্তি পূরণ না হওয়ায় List#contains(Object o)ভুল booleanমান ফিরে আসতে পারে ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.