سؤال

لا أفهم سلوك السبات عند تعيين قائمة ثنائية الاتجاه. يبدو أن عبارات SQL التي تنتجها السبات ليست مثالية بالنسبة لي. هل يمكن لأي شخص أن ينيرني؟

السيناريو هو ما يلي: لدي علاقة بين الوالدين والطفل. أقوم بتخطيط هذه العلاقة مع قائمة ثنائية الاتجاه.

بحسب ال دليل مرجعي لتوضيح السبات (الفصل: الارتباط ثنائي الاتجاه مع المجموعات المفهرسة) يجب أن يبدو التعيين هكذا:

@Entity
public class Parent {

    @Id  @GeneratedValue private long id;
    @Version  private int version;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", nullable=false)
    @org.hibernate.annotations.IndexColumn(name = "parent_index")
    List<Child> children = new ArrayList<Child>();

...

@Entity
public class Child {

    @Id @GeneratedValue private Long id;
    @Version private int version;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    private Parent parent;

...

ولكن في هذه الحالة ، تنتج السبات ثلاثة عبارات SQL عند استمرار أحد الوالدين مع طفل واحد:

Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)
Hibernate: update Child set parent_id=?, parent_index=? where id=?

يبدو أن البيان الثالث لا لزوم له parent_id و parent_index يبدو أنه تم تعيينه بالفعل في البيان الثاني.

عندما أقوم بتغيير التعيين وأكرر السمات "updatable = false ، insertable = false'لإعلان @joincolumn في الوالد مثل هذا:

@Entity
public class Parent {

    @Id  @GeneratedValue private long id;
    @Version  private int version;
    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    @org.hibernate.annotations.IndexColumn(name = "parent_index")
    List<Child> children = new ArrayList<Child>();

...

@Entity
public class Child {

    @Id @GeneratedValue private Long id;
    @Version private int version;
    private String name;

    @ManyToOne
    @JoinColumn(name = "parent_id", updatable = false, insertable = false, nullable=false)
    private Parent parent;

...

... ثم يبدو أن السبات ينتج عنه SQL أكثر تحسناً:

Hibernate: insert into Parent (name, version, id) values (?, ?, ?)
Hibernate: insert into Child (name, price, version, parent_id, parent_index, id) values (?, ?, ?, ?, ?, ?)

يبدو رمز العميل هكذا:

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();

    Parent newParent = new Parent();
    newParent.setName("Parent1");

    Child newChild = new Child();
    newChild.setName("Child1");

    newParent.getChildren().add(newChild);
    newChild.setParent(newParent);

    em.persist(newParent);

    em.flush();
    tx.commit();

أنا أستخدم Hibernate-EntityManager 3.4.0.ga.

ماذا ينقصني؟ هل الدليل المرجعي للسبات غير صحيح ، أم أنني أطل على شيء ما؟

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

المحلول

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

في الفصل 2.2.5.3.1.1. ثنائية الاتجاه وذكر بوضوح:

لرسم خريطة ثنائية الاتجاه إلى الكثيرين ، مع الجانب الآخر كجانب امتلاك ، يجب عليك إزالة العنصر mappedby وتعيين العديد على @joincolumn على أنه قابل للإدراج وقابل للتحديث إلى خطأ. من الواضح أن هذا الحل غير محسن وسيقوم بإنتاج بعض عبارات التحديث الإضافية.

ربما لن يضر بتكرار هذه المعلومات الفصل 2.4.6.2.1. ارتباط ثنائي الاتجاه مع المجموعات المفهرسة .

الآن يبقى السؤال: إذا أكررت سمات joincolumn "updatable = false" و "insertable = false" على الوالد (انظر الكود في المنشور الأول) ، يبدو أن عبارات التحديث الإضافية لا يتم إنتاجها ... هل هذا حل شرعي ؟ أم أن هذا يؤدي إلى مشكلة أخرى؟

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