我不明白映射双向列表时 Hibernate 的行为。 Hibernate 生成的 SQL 语句对我来说似乎不是最佳的。有人可以启发我吗?
场景如下:我有一对多的父子关系。我用双向列表来映射这种关系。
根据Hibernate 注解参考指南 http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/(章节:与索引集合的双向关联)映射应该如下所示:
@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
and parent_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;
...
...那么 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 参考指南是否不正确,或者我是否忽略了某些内容?