web-dev-qa-db-ja.com

Hibernate 3.5の@OrderColumnアノテーション

Hibernate 3.5で@OrderColumnアノテーションを使用しようとしています

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
private List<Children> childrenCollection;

データを取得するとき、すべてが正常に動作します。しかし、リストの要素を並べ替えて、新しい順序をデータベースに保存することはできません。

25
Piotr Gwiazda

@OneToMany(mappedBy = "...")と@OrderColumnの組み合わせはHibernateではサポートされていません。このJIRAの問題は、この無効な組み合わせが使用された場合により明確なエラーメッセージをスローするリクエストを追跡します: http://opensource.atlassian.com/projects/hibernate/browse/HHH-539

これは主に奇妙な関係パターンのためにサポートされていないと思います。上記の注釈は、リレーションシップの「1」側がリレーションシップをデータベースにフラッシュする方法を決定することを示していますが、順序/位置は「多」側でのみリストを調べて利用できます。要素のメンバーシップと順序の両方を知っているので、「多くの」側が関係を所有する方が理にかなっています。

Hibernate Annotationsのドキュメントでは、この状況について詳細に説明しています。

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype-in​​dexbidir

回避策は、 "mappedBy"属性を削除することです。これにより、関連付けは、ターゲットテーブルの列ではなく、デフォルトの結合テーブル戦略を使用します。 @JoinTableアノテーションを使用して、結合テーブルの名前を指定できます。

この変更の正味の効果は、関係の「多」側が関係の持続方法を決定することです。 Javaコードは、エンティティをフラッシュするときにHibernateが「1」側を無視するため、リストが適切に更新されるようにする必要があります。

それでもJavaで「片側」にアクセスできるようにしたい場合は、

@ManyToOne
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false)
29
Peter Centgraf

このようなことをしてください:

@Entity
class Parent {

    @OneToMany
    @OrderColumn(name = "pos")
    List<Child> children;
}

@Entity
class Child {

    @ManyToOne
    Parent parent;
    @Column(name = "pos")
    Integer index;

    @PrePersist
    @PreUpdate
    private void prepareIndex() {
        if (parent != null) {
            index = parent.children.indexOf(this);
        }
    }
}
10
Daniel De León

関連付けの所有者にOrderColumnを指定してみてください。または、マッピングで所有者を子に置き、所有者を親にする必要があります(双方向の関連付けでは、所有者はキーワードmapByを持たない所有者です。ここでは、このキーワードを親のクラスに置きます。親のクラスが所有者ではないことを意味します)

子クラスでは、parentCollectionにキーワードmappedByが必要です。ただし、childrenCollectionではありません。
そしてあなたの親クラスには、次のようなアノテーション@JoinTableが必要です:

@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
@JoinTable( name = "<NAME_OF_YOUR_TABLE>", joinColumns = @JoinColumn( <JOIN_COLUMNS_...> )
private List<Children> childrenCollection;
3
Nico