我不了解映射双向列表时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") Listchildren = new ArrayList (); ... @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") Listchildren = new ArrayList (); ... @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参考指南不正确,还是我忽略了什么?
好的,我没有仔细阅读"注释参考指南".
在第2.2.5.3.1.1节中.双向说明清楚:
要将双向一个映射到多个,以一对多方作为拥有方,您必须删除mappedBy元素并将多个@JoinColumn设置为可插入且可更新为false.此解决方案显然未经过优化,并将生成一些额外的UPDATE语句.
重复第2.4.6.2.1节中的这些信息可能不会有什么坏处.与索引集合的双向关联.
现在问题仍然存在:如果我在Parent上重复@JoinColumn属性'updatable = false'和'insertable = false'(请参阅第一篇文章中的代码),其他更新语句似乎不会产生...这是一个合法的解决方法?或者这会导致另一个问题吗?