متى يتم استخدام معكوس = خطأ في علاقات NHibernate / Hibernate OneToMany؟

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

سؤال

لقد كنت أحاول التعامل مع السمة العكسية لـ Hibernate، ويبدو أنها مجرد واحدة من تلك الأشياء الصعبة من الناحية المفاهيمية.

جوهر ما أحصل عليه هو أنه عندما يكون لديك كيان أصل (على سبيل المثال.الأصل) الذي يحتوي على مجموعة من الكائنات التابعة باستخدام واحد لكثير تعيين معكوس = صحيح على التعيين يخبر Hibernate أن "الجانب الآخر (الطفل) يتحمل مسؤولية تحديث نفسه للحفاظ على مرجع المفتاح الخارجي في جدوله".

يبدو أن القيام بذلك له فائدتان عندما يتعلق الأمر بإضافة الأطفال إلى المجموعة في التعليمات البرمجية الخاصة بك، ثم حفظ الأصل (مع مجموعة تتالي الكل): قمت بحفظ نتيجة غير ضرورية في قاعدة البيانات (لأنه بدون المجموعة العكسية، يعتقد Hibernate أن لديه مكانين لتحديث علاقة FK)، ووفقًا للمستندات الرسمية:

إذا تم الإعلان عن عمود الجمعية غير فارغة ، فقد يتسبب nhibernate في انتهاكات للقيود عندما يقوم بإنشاء أو تحديث الجمعية.لمنع هذه المشكلة ، يجب عليك استخدام ارتباط ثنائي الاتجاه مع العديد من نهاية القيمة (المجموعة أو الحقيبة) التي تم وضع علامة عليها على أنها عكسية = "صحيح".

ويبدو أن كل هذا منطقي حتى الآن.ما لا أحصل عليه هو هذا:متى لا هل تريد استخدام inverse=true في علاقة رأس بأطراف؟

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

المحلول

كما يقول ماتيو، الحالة الوحيدة التي لا تريد فيها تعيين العكس = صحيح هي عندما لا يكون من المنطقي أن يكون الطفل مسؤولاً عن تحديث نفسه، كما هو الحال في الحالة التي لا يكون فيها الطفل على علم بوالديه.

لنجرب عالمًا حقيقيًا، وليس مثالًا مفتعلًا على الإطلاق:

<class name="SpyMaster" table="SpyMaster" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
  <set name="Spies" table="Spy" cascade="save-update">
    <key column="SpyMasterId"/>
    <one-to-many class="Spy"/>
  </set>
</class>

<class name="Spy" table="Spy" lazy="true">
  <id name="Id">
    <generator class="identity"/>
  </id>
  <property name="Name"/>
</class>

من الممكن أن يكون لدى أسياد التجسس جواسيس، لكن الجواسيس لا يعرفون أبدًا من هو رئيس التجسس، لأننا لم ندرج العلاقة بين شخصين في فئة التجسس.أيضًا (بشكل ملائم) قد يتحول الجاسوس إلى مارق وبالتالي لا يحتاج إلى أن يكون مرتبطًا بمسؤول تجسس.يمكننا إنشاء الكيانات على النحو التالي:

var sm = new SpyMaster
{
    Name = "Head of Operation Treadstone"
};
sm.Spies.Add(new Spy
{
    Name = "Bourne",
    //SpyMaster = sm // Can't do this
});
session.Save(sm);

في مثل هذه الحالة، يمكنك تعيين عمود FK ليكون فارغًا لأن عملية الحفظ sm سيتم إدراجها في جدول SpyMaster وجدول Spy، وبعد ذلك فقط سيتم تحديث جدول Spy لتعيين FK.في هذه الحالة، إذا أردنا تعيين inverse = true، فلن يتم تحديث FK أبدًا.

نصائح أخرى

على الرغم من الإجابة المقبولة ذات التصويت العالي، لدي إجابة أخرى لذلك.

خذ بعين الاعتبار مخطط الفصل مع هذه العلاقات:

Parent => list of Items
Item => Parent

لا أحد أبدًا قال، أن علاقة العنصر => الأصل زائدة عن العلاقة الأصل => العناصر.يمكن أن يشير العنصر إلى أي والد.

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

كل ما عليك فعله لتعيين ذلك مع NH هو:

  • استخدم نفس المفتاح الخارجي لكلتا العلاقتين
  • أخبر NH أن أحدهما (القائمة) زائد عن الحاجة إلى الآخر ويمكن تجاهله عند تخزين الكائن.(وهذا ما تفعله NH بالفعل inverse="true")

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


مشكلة التجسس:إنها مناقشة مختلفة تماما لو تريد دعم مرجع من العنصر إلى الأصل.هذا الأمر متروك لنموذج عملك، ولا تتخذ NH أي قرارات في هذا الشأن.إذا كانت إحدى العلاقات مفقودة، فلا يوجد بالطبع تكرار ولا يوجد استخدام للمعكوس.

سوء استخدام: إذا كنت تستخدم inverse="true" في قائمة لا تحتوي على أي تكرار في الذاكرة، فلن يتم تخزينها.إذا لم تحدد العكس = "true" إذا كان يجب أن يكون هناك، فقد تقوم NH بتخزين المعلومات الزائدة مرتين.

إذا كنت تريد أن يكون لديك ارتباط أحادي الاتجاه، على سبيل المثال.أن الأطفال لا يستطيعون الانتقال إلى الوالدين.إذا كان الأمر كذلك، فيجب أن يكون عمود FK الخاص بك NULLABLE لأنه سيتم حفظ الأطفال قبل الأصل.

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