2009-02-02 104 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'(看第一篇文章中的代码),额外的更新语句似乎不会被生成...是这是一个合法的解决方法?或者这是否会导致另一个问题?