Hibernate 3.5で@OrderColumn
アノテーションを使用しようとしています
@OneToMany(mappedBy = "parent",fetch=FetchType.EAGER, cascade=CascadeType.ALL)
@OrderColumn(name = "pos")
private List<Children> childrenCollection;
データを取得するとき、すべてが正常に動作します。しかし、リストの要素を並べ替えて、新しい順序をデータベースに保存することはできません。
@OneToMany(mappedBy = "...")と@OrderColumnの組み合わせはHibernateではサポートされていません。このJIRAの問題は、この無効な組み合わせが使用された場合により明確なエラーメッセージをスローするリクエストを追跡します: http://opensource.atlassian.com/projects/hibernate/browse/HHH-539
これは主に奇妙な関係パターンのためにサポートされていないと思います。上記の注釈は、リレーションシップの「1」側がリレーションシップをデータベースにフラッシュする方法を決定することを示していますが、順序/位置は「多」側でのみリストを調べて利用できます。要素のメンバーシップと順序の両方を知っているので、「多くの」側が関係を所有する方が理にかなっています。
Hibernate Annotationsのドキュメントでは、この状況について詳細に説明しています。
回避策は、 "mappedBy"属性を削除することです。これにより、関連付けは、ターゲットテーブルの列ではなく、デフォルトの結合テーブル戦略を使用します。 @JoinTableアノテーションを使用して、結合テーブルの名前を指定できます。
この変更の正味の効果は、関係の「多」側が関係の持続方法を決定することです。 Javaコードは、エンティティをフラッシュするときにHibernateが「1」側を無視するため、リストが適切に更新されるようにする必要があります。
それでもJavaで「片側」にアクセスできるようにしたい場合は、
@ManyToOne
@JoinColumn(name="...", insertable=false, updatable=false, nullable=false)
このようなことをしてください:
@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);
}
}
}
関連付けの所有者に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;