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エンティティのコレクションを含むBar

これを行うには、コレクションにHibernate@OrderByアノテーションをアノテーションします。 順序付けを行うフィールドと方向を指定します。

@OrderBy(clause = "NAME DESC")
Set<Foo> fooList = new HashSet();

注釈のclause引数に注意してください。 これは、同様の @OrderBy JPAアノテーションと比較して、Hibernateの@OrderByに固有のものです。 このアプローチを同等のJPAと区別する別の特徴は、引数が、FOOテーブルのNAME列に基づいて並べ替えが行われることを示していることです。 Fooname属性。

次に、BarsFoosの実際の並べ替えを見てみましょう。

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ベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。