映射双向列表时,我不了解Hibernate的行为。Hibernate生成的SQL语句对我来说并不是最佳的。有人可以启发我吗?
情况如下:我有一对多的父子关系。我将此关系与双向列表映射。
根据《Hibernate注释参考指南》(第7章:与索引集合的双向关联),映射应如下所示:
@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似乎已经在第二条语句中设置了。
parent_id
parent_index
当我更改映射并在父级中 @JoinColumn 的声明中重复属性’ updatable = false,insertable = false ‘时,如下所示: __
@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-entitymanager3.4.0.GA。
我想念什么?《 Hibernate参考指南》是否不正确,还是我忽略了某些内容?
好的,我没有充分阅读《注释参考指南》。
在第2.2.5.3.1.1章中。双向明确指出:
要以一对多方为拥有方映射双向一对多,您必须删除mapledBy元素,并将多对一设置为@JoinColumn,以将其可插入,并将其可更新为false。 该解决方案显然未进行优化,并且会生成一些其他UPDATE语句 。
在第2.4.6.2.1节中重复此信息可能不会受到伤害。与索引集合的双向关联。
现在的问题仍然存在:如果我在Parent上重复@JoinColumn属性’updatable = false’和’insertable = false’(请参阅第一篇文章中的代码),似乎不会产生其他更新语句…这是一个合理的解决方法?还是会导致另一个问题?