7

双方向リストをマッピングするときの 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_idandparent_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 リファレンス ガイドは正しくありませんか、それとも何か見落としていますか?

4

1 に答える 1