Hibernateでの並べ替え
1. 概要
この記事では、Hibernateクエリ言語(HQL)とCriteria APIの両方を使用して、Hibernateで並べ替える方法について説明します。
2. HQLによる並べ替え
HibernateのHQLでの並べ替えは、 OrderBy句をHQLクエリ文字列に追加するのと同じくらい簡単です。
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クエリ文字列の OrderBy句に追加できます。
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次第です。 このデフォルトの処理は、 aNULLSFIRSTまたはNULLSLAST句をHQLクエリ文字列に配置することでオーバーライドできます。
この簡単な例では、結果リストの最後にnullを配置します。
String hql = "FROM Foo f ORDER BY f.name NULLS LAST";
Query query = sess.createQuery(hql);
がnullの場合は1、それ以外の場合はで生成されたSQLクエリの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対多の関係の並べ替え
複雑な並べ替えのケースを分析してみましょう。1対多の関係でエンティティを並べ替える– Fooエンティティのコレクションを含む
これを行うには、コレクションにHibernate@OrderByアノテーションをアノテーションします。 順序付けを行うフィールドと方向を指定します。
@OrderBy(clause = "NAME DESC")
Set<Foo> fooList = new HashSet();
注釈のclause引数に注意してください。 これは、同様の @OrderBy JPAアノテーションと比較して、Hibernateの@OrderByに固有のものです。 このアプローチを同等のJPAと区別する別の特徴は、句引数が、FOOテーブルのNAME列に基づいて並べ替えが行われることを示していることです。 Fooのname属性。
次に、BarsとFoosの実際の並べ替えを見てみましょう。
String hql = "FROM Bar b ORDER BY b.id";
Query query = sess.createQuery(hql);
の結果のSQLステートメントは、ソートされたFooのが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の場合のように、リストをソートできないことです。 Hibernateのドキュメントには次のように記載されています。
「Hibernateは現在、たとえば@ElementCollectionの@OrderByを無視します。 リスト
。 要素の順序は、データベースから返されるものであり、未定義です。」
補足として、HibernateのレガシーXML構成を使用し、
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を使用すると、デフォルトを簡単に変更し、昇順リストの最後にnullを配置できます。
Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.asc("name").nulls(NullPrecedence.LAST));
基になるSQLクエリは次のとおりです– がnullの場合は1、それ以外の場合は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
または、nullを降順リストの先頭に配置することもできます。
Criteria criteria = sess.createCriteria(Foo.class, "FOO");
criteria.addOrder(Order.desc("name").nulls(NullPrecedence.FIRST));
対応するSQLクエリは次のとおりです– がnullの場合は0、それ以外の場合は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
並べ替える属性がintのようなプリミティブ型の場合、PresisitenceExceptionがスローされることに注意してください。
たとえば、 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チュートリアルの実装は、 githubプロジェクトにあります。これはEclipseベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。