Hibernateでのソート
1. 概要
この記事では、Hibernate Query Language(HQL)とCriteria APIの両方を使用したhow to Sort with Hibernateについて説明します。
参考文献:
Hibernate:保存、永続化、更新、マージ、saveOrUpdate
Hibernate書き込みメソッドの迅速かつ実用的なガイド:保存、永続化、更新、マージ、saveOrUpdate。
2. HQLによる並べ替え
HibernateのHQLを使用した並べ替えは、HQLクエリ文字列にOrder By句を追加するのと同じくらい簡単です。
String hql = "FROM Foo f ORDER BY f.name";
Query query = sess.createQuery(hql);
このコードが実行されると、Hibernateは次のSQLクエリを生成します。
Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_ from
FOO foo0_ order by foo0_.NAME
デフォルトのソート順は昇順です。 これが、生成されたSQLクエリに注文条件ascが含まれていない理由です。
2.1. 明示的な並べ替え順序の使用
並べ替え順序を手動で指定するには、HQLクエリ文字列に順序の方向を含める必要があります。
String hql = "FROM Foo f ORDER BY f.name ASC";
Query query = sess.createQuery(hql);
この例では、HQLでasc句を設定することが、生成されたSQLクエリに含まれていました。
Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_
from FOO foo0_ order by foo0_.NAME ASC
2.2. 複数の属性による並べ替え
オプションの並べ替え順序とともに、複数の属性をHQLクエリ文字列のOrder By句に追加できます。
String hql = "FROM Foo f ORDER BY f.name DESC, f.id ASC";
Query query = sess.createQuery(hql);
生成されたSQLクエリはそれに応じて変更されます。
Hibernate: select foo0_.ID as ID1_0_, foo0_.NAME as NAME2_0_
from FOO foo0_ order by foo0_.NAME DESC, foo0_.ID ASC
2.3. ヌル値のソート優先順位の設定
デフォルトでは、ソートする属性にnullの値がある場合、優先順位を決定するのはRDMS次第です。 このデフォルトの処理は、a NULLS FIRST or NULLS LAST clause in the HQL query stringを配置することでオーバーライドできます。
この単純な例では、結果リストの最後にヌルを配置しています。
String hql = "FROM Foo f ORDER BY f.name NULLS LAST";
Query query = sess.createQuery(hql);
generated SQL queryのis null then 1 else 0句を見てみましょう。
Hibernate: select foo0_.ID as ID1_1_, foo0_.NAME as NAME2_1_,
foo0_.BAR_ID as BAR_ID3_1_, foo0_.idx as idx4_1_ from FOO foo0_
order by case when foo0_.NAME is null then 1 else 0 end, foo0_.NAME
2.4. 1対多の関係の並べ替え
複雑な並べ替えのケースを分析してみましょう:sorting entities in a one to many relation –Fooエンティティのコレクションを含むBar。
これを行うには、コレクションにthe Hibernate @OrderBy annotationの注釈を付けます。順序付けを行うフィールドと方向を指定します。
@OrderBy(clause = "NAME DESC")
Set fooList = new HashSet();
注釈に対するclause引数に注意してください。 これは、同様の@OrderBy JPAアノテーションと比較して、Hibernateの@OrderByに固有です。 このアプローチを同等のJPAと区別する別の特徴は、clause引数が、nameではなくFOOテーブルのNAME列に基づいてソートが行われることを示していることです。 Fooのs属性。
次に、BarsとFoosの実際の並べ替えを見てみましょう。
String hql = "FROM Bar b ORDER BY b.id";
Query query = sess.createQuery(hql);
resulting SQL statementは、ソートされたFoo’sがfooList:に配置されていることを示しています
Hibernate: select bar0_.ID as ID1_0_, bar0_.NAME as NAME2_0_ from BAR bar0_
order by bar0_.ID Hibernate: select foolist0_.BAR_ID as BAR_ID3_0_0_,
foolist0_.ID as ID1_1_0_, foolist0_.ID as ID1_1_1_, foolist0_.NAME as
NAME2_1_1_, foolist0_.BAR_ID as BAR_ID3_1_1_, foolist0_.idx as idx4_1_1_
from FOO foolist0_ where foolist0_.BAR_ID=? order by foolist0_.NAME desc
覚えておくべきことの1つは、JPAの場合と同様にnot possible to to sort Listsであるということです。 Hibernateドキュメントの状態:
「Hibernateは現在、たとえば、@ ElementCollectionの@OrderByを無視しています。 List
。 要素の順序は、データベースによって返されるとおりであり、未定義です。」
補足として、HibernateのレガシーXML構成を使用し、<List..>要素を<Bag…>要素に置き換えることで、この制限を回避することができます。
3. Hibernate基準での並べ替え
Criteria Object APIは、並べ替えを管理するためのメインAPIとしてOrderクラスを提供します。
3.1. 並べ替え順序の設定
Orderクラスには、ソート順を設定するための2つのメソッドがあります。
-
*asc*(String attribute):クエリをattributeで昇順で並べ替えます。
-
*desc*(String attribute):クエリをattributeで降順で並べ替えます。
簡単な例から始めましょう–単一のid属性でソートします。
Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("id"));
ascメソッドの引数では大文字と小文字が区別され、並べ替える属性のnameと一致する必要があることに注意してください。
HibernateCriteriaのObjectAPIは、並べ替え順序の方向を明示的に設定します。これは、コードによって生成されるSQLステートメントに反映されます。
Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_
from FOO this_ order by this_.ID sac
3.2. 複数の属性による並べ替え
以下の例のように、複数の属性で並べ替えるには、OrderオブジェクトをCriteriaインスタンスに追加するだけで済みます。
Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name"));
criteria.addOrder(Order.asc("id"));
SQLで生成されるクエリは次のとおりです。
Hibernate: select this_.ID as ID1_0_0_, this_.NAME as NAME2_0_0_ from
FOO this_ order by this_.NAME asc, this_.ID sac
3.3. ヌル値のソート優先順位の設定
デフォルトでは、ソートする属性にnullの値がある場合、優先順位を決定するのはRDMS次第です。 Hibernate Criteria Object APIを使用すると、昇順リストのデフォルトとplace nulls at the endを簡単に変更できます。
Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));
基になるSQLクエリは次のとおりです–is null then 1 else 0句を使用します。
Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_,
this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as
ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when
this_.NAME is null then 1 else 0 end, this_.NAME asc
または、降順リストのplace the nulls at the beginningを指定することもできます。
Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));
対応するSQLクエリは次のとおりです–is null then 0 else 1句を使用します。
Hibernate: select this_.ID as ID1_1_1_, this_.NAME as NAME2_1_1_,
this_.BAR_ID as BAR_ID3_1_1_, this_.idx as idx4_1_1_, bar2_.ID as
ID1_0_0_, bar2_.NAME as NAME2_0_0_ from FOO order by case when
this_.NAME is null then 0 else 1 end, this_.NAME desc
if the attribute to sort by is a primitive type like an int, a PresisitenceException will thrownであることに注意してください。
たとえば、f.anIntVariableの値がnullの場合、クエリの実行は次のようになります。
String jql = "Select f from Foo as f order by f.anIntVariable desc NULLS FIRST";
Query sortQuery = entityManager.createQuery(jql);
投げます:
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException:
Null value was assigned to a property of primitive type setter of
com.cc.jpa.example.Foo.anIntVariable
4. 結論
この記事では、Hibernateを使用したソートについて説明します-単純なエンティティと1対多の関係にあるエンティティに使用可能なAPIを使用します。
このHibernateSorting Tutorialの実装は、the github projectにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。