我不了解映射双向列表时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_id
和parent_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参考指南不正确,还是我忽略了什么?
答案 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'(请参阅第一篇文章中的代码),其他更新语句似乎不会产生......这是合法的解决方法?或者这会导致另一个问题吗?