web-dev-qa-db-ja.com

JPA / hibernateのソートされたコレクション@OrderBy vs @Sort

注文された子オブジェクトのコレクション(ここでは猫と子猫の例)が欲しいです。そして、新しい要素を追加する順序を維持します。

_@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  private List<Kitten> kittens;

  public void setKittens(List<Kitten> kittens) { this.kittens = kittens; }
  public List<Kitten> getKittens() { return kittens; } 
}
_

cat.getKittens.add(newKitten)を実行すると、名前による順序が壊れます。

コレクションを常に順序付けする作業を休止状態にさせることは可能ですか? @ Sort hibernate アノテーションを使用して?
@ Sortには、Comparableインターフェースの実装を余儀なくされるという欠点があります...それを行うための正しい「純粋なJPA」方法は何でしょうか?すべてをDBに保存してリロードしますか? @OrderByと@Sortを組み合わせるのは理にかなっていますか?

Updateこれまでの解決策は、@ OrderByと@Sortを組み合わせることです。 @OrderByにより、生成されたSQLで_ORDER BY_句が生成され、パフォーマンスが向上します(Javaはソートされたコンテナへの挿入時に再び「ソート」されると仮定しますが、要素は既にソートされています)@Sortと実装されたComparableインターフェースは、常にソートされたコンテナになります。 SortedSetの代わりにListを使用することに注意してください。ここに更新されたコード:

_@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  @Sort(type = SortType.NATURAL)
  private SortedSet<Kitten> kittens;

  public void setKittens(SortedSet<Kitten> kittens) { this.kittens = kittens; }
  public SortedSet<Kitten> getKittens() { return kittens; } 
}
_
31
adler

非標準の注釈を避けたい場合は、kittensにソート済みのCollection実装を使用させることができます。これにより、kittensが常にソートされた順序になります。このようなもの:

_@Entity 
public class Cat {
  @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL)
  @OrderBy("name ASC")
  private SortedSet<Kitten> kittens = new TreeSet<>();
}
_

このアプローチでは、Kittenを実装するためにComparableも必要です(または、ComparatorTreeSetコンストラクターに渡すこともできます)。また、Setを使用しているのは、標準のソート済みList実装を認識していないため、Catのリターにクローンがないと仮定しているためです。 = p。

更新:ゲッター/セッター定義でHibernateがどれほどうるさいのかわかりませんが、EclipseLinkではセッターを完全に削除し、返されたListをラップできましたCollections.unmodifiableList(...)呼び出しのゲッター。次に、コレクションを変更するための特別なメソッドを定義しました。同じことを行い、呼び出し元に、ソートされた順序で要素を挿入するaddメソッドの使用を強制することもできます。 Hibernateがgetter/setterを持たないことについて苦情を言う場合、アクセス修飾子を変更できますか?非標準の依存関係を回避するためにどれだけ進んでいくかが問題になると思います。

22
DannyMo

Hibernateの最新バージョンは、これを達成するために新しい注釈を使用します。

@SortNatural
@OrderBy("name ASC")
private SortedSet<Kitten> kittens = new TreeSet<>();

これには2つの部分があります。

  1. @OrderBy注釈は、関連レコードを取得するときに、データベースクエリにorder by句を追加することを指定します。
  2. @SortNatural注釈は、KittenComparableインターフェイスを実装し、TreeSetインスタンスを構築するときにその情報を使用することを前提としています。これを@SortComparatorアノテーションで置き換えることができます。これにより、Comparatorコンストラクターに渡されるTreeSetクラスを指定できます。

ドキュメントを参照してください: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#collections-sorted-set

17
mark.monteiro