双方向リストをマッピングするときの Hibernate の動作がわかりません。Hibernate が生成する SQL ステートメントは、私には最適ではないようです。誰かが私を啓発できますか?
シナリオは次のとおりです。1 対多の親子関係があります。この関係を双方向リストにマッピングします。
Hibernate Annotation Reference Guide (Chapter: Bidirectional association with indexed collection) によると、マッピングは次のようになります。
@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 は 1 つの子を持つ親を永続化するときに 3 つの 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
andparent_index
は 2 番目のステートメントで既に設定されているように見えるため、3 番目のステートメントは冗長なようです。
マッピングを変更し、属性 ' updateable = false, insertable = false ' を次のように親の@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 リファレンス ガイドは正しくありませんか、それとも何か見落としていますか?