هل من الممكن أن يتم تطبيق مفتاح خارجي دون تعيين كائن إلى كائن؟

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

سؤال

بافتراض توفير التعيينات التالية:

<class name="A" table="a_table">
  <id name="id"/>
  <many-to-one name="entityB" column="fk_B" not-null="false" unique="true"/>
</class>

<class name="B" table="b_table">
  <id name="id"/>
</class>

فئة جافا:

public class A {
   private long id;
   private B entityB;
   // getters and setters skipped
}

هل من الممكن تغيير رسم خرائط السبات بحيث لا يزال مفتاح الخارجية يتم تنفيذه وإنشائه عن طريق السبات عند بدء التشغيل, ، ولكن الطبقة A سيبدو كما يلي:

public class A {
   private long id;
   private long idOfB;
   // getters and setters skipped
}

أفهم أنه إذا قمت بتحويل <many-to-one... الى <property... هذا من شأنه أن ينجح ، ولكن لن يتم تطبيق المفتاح الخارجي بواسطة قاعدة البيانات.

أحتاج إلى القيام بذلك لأن الكائن B قد تتم تهيئة (أو لا) بشكل منفصل والتي تسبب في بعض الأحيانorg.hibernate.LazyInitializationException: could not initialize proxy - no Session استثناءات تحدث عندما a.getB() يسمى. أفضل أن أحصل عليها ك long idOfB وتحميل كائن كامل كلما كان ذلك ضروريًا ؛ هذا من شأنه أن يجعل تحميل الكائن A أسرع.

أعتقد أن سؤالي يشبه إلى حد كبير هذا, ، ومع ذلك ، فإن الحل المعروض (لاستخدام التحميل البطيء) غير مناسب في حالتي كما لو كنت أتصل a.getB().getId(), ، سأحصل LazyInitializationException بينما إذا اتصلت a.getIdOfB() لن أفعل.

شكرا جزيلا مقدما.

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

المحلول

كما قيل

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

لذلك نصيحتي هي: استخدم الأثنين

public class EntityA {

    private Integer idOfB;

    private EntityB entityB;

    // getter's and setter's

}

و

<class name="A" table="a_table">
    <id name="id"/>
    <property name="idOfB" column="fk_B" not-null="false" unique="true"/>
    <many-to-one name="entityB" update="false" insert="false" column="fk_B"/>
</class>

لاحظ عندما تشارك اثنين من الممتلكات نفس العمود ، عليك وضع إعدادات حول هذا الموضوع في خاصية واحدة فقط. خلاف ذلك ، فإن السبات سوف يشكو من بعض الأخطاء. وهذا ما يفسر سبب تحديد update = "false" و insert = "false" في خاصية entityB.

مع تحياتي،

نصائح أخرى

يمكنك دائمًا إنشاء مفتاح DDL الخارجي يدويًا في ملف HBM.XML الخاص بك:

<hibernate-mapping>
    ...
    <database-object>
        <create>[CREATE FK]</create>
        <drop>[DROP FK]</drop>
    </database-object> 
</hibernate-mapping>

يمكنك أيضًا تحديد هذا إذا كانت هناك لهجات مختلفة بحاجة إلى دعمها.

الدفع 5.7. كائنات قاعدة البيانات الإضافية

هناك نهج آخر يمكن أن تتخذه هو تحديد FK باستخدام رسم الخرائط B بدلاً من رسم الخرائط A. لقد أضفت رمز JPA ، يجب عليك ترجمة هذا إلى ملف تعيين Hibernate إذا كنت لا تستخدم التعليقات التوضيحية.

@Entity
public class B
{
    private long id;
    private List<A> aList;

    @Id
    @Column( name = "ID" )
    public long getId()
    {
        return id;
    }

    @OneToMany
    @JoinColumn( name = "B_ID" )
    public List<A> getAList()
    {
        return aList;
    }
    public void setId( long id )
    {
        this.id = id;
    }
    public void setAList( List<A> aList )
    {
        this.aList = aList;
    }        
}

أ. جافا لن يبدو هكذا:

@Entity
public class A
{
    private long id;
    private long idOfB;

    @Id
    @Column( name = "ID" )
    public long getId()
    {
        return id;
    }
    @Column( name = "B_ID" )
    public long getIdOfB()
    {
        return idOfB;
    }
    public void setId( long id )
    {
        this.id = id;
    }
    public void setIdOfB( long idOfB )
    {
        this.idOfB = idOfB;
    }   
}

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

في حال كنت تستخدم الربيع ، يمكنك استخدام OpenEtityManagerInViewFilter حتى يتم فتح الجلسة حتى يتم عرض العرض.

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