2009-02-02 107 views
7

我不明白映射雙向列表時Hibernate的行爲。 Hibernate產生的SQL語句對我來說似乎並不是最優的。有人可以啓發我嗎?用休眠映射雙向列表

該場景如下:我有一對多的親子關係。我將這種關係映射到雙向列表。

按照Hibernate Annotation Reference Guide(章:使用索引的集合雙向關聯)的映射應該是這樣的:

@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_idparent_index似乎已經在第二條語句中設置。

當我改變映射和重複屬性「更新=假,可插入=假」到@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.

我錯過了什麼? 「Hibernate參考指南」不正確,還是我忽略了某些內容?

回答

6

好吧,我沒有仔細閱讀註解參考指南。

在第二章2.2.5.3.1.1. Bidirectional它明確規定:

要映射雙向一對多,與一個一對多側的擁有方,你要刪除的mappedBy元素,並設置多對一@JoinColumn作爲可插入和可更新爲false。 這個解決方案顯然沒有被優化,並且會產生一些額外的UPDATE語句

Chapter 2.4.6.2.1. Bidirectional association with indexed collections中重複此信息可能不會造成傷害。

現在的問題仍然存在:如果我在Parent上重複@JoinColumn屬性的'updatable = false'和'insertable = false'(看第一篇文章中的代碼),額外的更新語句似乎不會被生成...是這是一個合法的解決方法?或者這是否會導致另一個問題?