使用Hibernate映射双向列表

时间:2009-02-02 23:13:41

标签: hibernate list jpa mapping bidirectional

我不了解映射双向列表时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;

...

但在这种情况下,Hibernate在持有一个子节点的父节点时会生成三个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似乎已在第二个陈述中设置。

当我更改映射并重复属性' updatable = false,insertable = false '到Parent中 @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;

...

...然后Hibernate似乎产生了更优化的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参考指南不正确,还是我忽略了什么?

1 个答案:

答案 0 :(得分: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'(请参阅第一篇文章中的代码),其他更新语句似乎不会产生......这是合法的解决方法?或者这会导致另一个问题吗?