JPA基準クエリ

JPA基準クエリ

1. 概要

このチュートリアルでは、非常に便利なJPA機能である基準クエリについて説明します。

生のSQLを実行せずにクエリを作成できるだけでなく、Hibernateの主要な機能の1つであるクエリをオブジェクト指向で制御できます。 Criteria APIを使用すると、プログラムで条件クエリオブジェクトを構築でき、さまざまな種類のフィルタールールと論理条件を適用できます。

Since Hibernate 5.2, the Hibernate Criteria API is deprecated and new development is focused on the JPA Criteria API.HibernateとJPAを使用して基準クエリを作成する方法について説明します。

2. Mavenの依存関係

APIを説明するために、リファレンスJPA実装であるHibernateを使用します。

Hibernateを使用するには、Hibernateの最新バージョンをpom.xmlファイルに追加してください。


    org.hibernate
    hibernate-core
    5.3.2.Final

Hibernateの最新バージョンはhere.で見つけることができます

3. 基準を使用した簡単な例

まず、Criteriaクエリを使用してデータを取得する方法を見てみましょう。 データベースから特定のクラスのすべてのインスタンスを取得する方法を見ていきます。

データベース内のタプル“ITEM”を表すItemクラスがあります。

public class Item implements Serializable {

    private Integer itemId;
    private String itemName;
    private String itemDescription;
    private Integer itemPrice;

   // standard setters and getters
}

データベースから「ITEM”」のすべての行を取得する簡単な条件クエリを見てみましょう。

Session session = HibernateUtil.getHibernateSession();
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery cr = cb.createQuery(Item.class);
Root root = cr.from(Item.class);
cr.select(root);

Query query = session.createQuery(cr);
List results = query.getResultList();

上記のクエリは、すべてのアイテムを取得する方法の簡単なデモです。 何が行われたかを段階的に見てみましょう。

  1. SessionFactoryオブジェクトからSessionのインスタンスを作成します

  2. getCriteriaBuilder()メソッドを呼び出して、CriteriaBuilderのインスタンスを作成します

  3. CriteriaBuildercreateQuery() methodを呼び出して、CriteriaQueryのインスタンスを作成します

  4. SessioncreateQuery()メソッドを呼び出して、Queryのインスタンスを作成します

  5. 結果が得られるqueryオブジェクトのgetResultList()メソッドを呼び出します

基本を説明したので、基準クエリのいくつかの機能に移りましょう。

3.1. Expressionsの使用

The CriteriaBuilder can be used to restrict query results based on specific conditions.CriteriaQuery where()メソッドを使用して、CriteriaBuilder.によって作成されたExpressionsを提供します

一般的に使用されるExpressionsの例を次に示します。

1000を超える価格のアイテムを取得するには:

cr.select(root).where(cb.gt(root.get("itemPrice"), 1000));

次に、itemPriceが1000未満のアイテムを取得します。

cr.select(root).where(cb.lt(root.get("itemPrice"), 1000));

itemNamesを持つアイテムには、Chairが含まれます。

cr.select(root).where(cb.like(root.get("itemName"), "%chair%"));

100から200の間にitemPriceがあるレコード:

cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200));

指定されたプロパティがnullかどうかを確認するには:

cr.select(root).where(cb.isNull(root.get("itemDescription")));

指定されたプロパティがnullでないかどうかを確認するには:

cr.select(root).where(cb.isNotNull(root.get("itemDescription")));

メソッドisEmpty()およびisNotEmpty()を使用して、クラス内のListが空であるかどうかをテストすることもできます。

ここで、上記の比較を2つ以上組み合わせることができるかどうかという疑問が避けられません。 もちろん、答えは「はい」です–the Criteria API allows us to easily chain expressions

Predicate[] predicates = new Predicate[2];
predicates[0] = cb.isNull(root.get("itemDescription"));
predicates[1] = cb.like(root.get("itemName"), "chair%");
cr.select(root).where(predicates);

論理演算で2つの式を追加するには:

Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000);
Predicate chairItems = cb.like(root.get("itemName"), "Chair%");

上記で定義された条件がLogical ORで結合されたアイテム:

cr.select(root).where(cb.or(greaterThanPrice, chairItems));

上記で定義された条件に一致するアイテムをLogical ANDで結合して取得するには:

cr.select(root).where(cb.and(greaterThanPrice, chairItems));

3.2. ソート

Criteriaの基本的な使用法がわかったので、Criteriaの並べ替え機能を見てみましょう。

次の例では、名前の昇順でリストを並べ替えてから、価格の降順でリストを並べ替えます。

cr.orderBy(
  cb.asc(root.get("itemName")),
  cb.desc(root.get("itemPrice")));

次のセクションでは、集計関数を実行する方法を見ていきます。

3.3. 射影、集計、およびグループ化関数

これまで、基本的なトピックのほとんどを取り上げてきました。 次に、さまざまな集計関数を見てみましょう。

行数を取得する:

CriteriaQuery cr = cb.createQuery(Long.class);
Root root = cr.from(Item.class);
cr.select(cb.count(root));
Query query = session.createQuery(cr);
List itemProjected = query.getResultList();

以下は、集計関数の例です。

AverageAggregate関数:

CriteriaQuery cr = cb.createQuery(Double.class);
Root root = cr.from(Item.class);
cr.select(cb.avg(root.get("itemPrice")));
Query query = session.createQuery(cr);
List avgItemPriceList = query.getResultList();

利用可能な他の有用な集計メソッドは、sum()max()min(),count()などです。

3.4. CriteriaUpdate

JPA 2.1以降、CriteriaAPIを使用してデータベース更新を実行するためのサポートがあります。

CriteriaUpdateには、データベースレコードに新しい値を提供するために使用できるset()メソッドがあります。

CriteriaUpdate criteriaUpdate = cb.createCriteriaUpdate(Item.class);
Root root = criteriaUpdate.from(Item.class);
criteriaUpdate.set("itemPrice", newPrice);
criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();

上記のスニペットでは、CriteriaBuilderからCriteriaUpdate<Item> のインスタンスを作成し、そのset()メソッドを使用してitemPrice.に新しい値を提供します。複数のプロパティを更新するには、次のことを行う必要があります。 set()メソッドを複数回呼び出します。

3.5. CriteriaDelete

CriteriaDelete,は、その名前が示すように、CriteriaAPIを使用した削除操作を有効にします。 必要なのは、CriteriaDeleteのインスタンスを作成し、where()メソッドを使用して制限を適用することだけです。

CriteriaDelete criteriaDelete = cb.createCriteriaDelete(Item.class);
Root root = criteriaDelete.from(Item.class);
criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice));

Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();

4. HQLに対する利点

前のセクションでは、基準クエリの使用方法について説明しました。

明らかに、the main and most hard-hitting advantage of Criteria queries over HQL is the nice, clean, Object Oriented API.

単純なHQLと比較して、より柔軟で動的なクエリを簡単に記述できます。 ロジックはIDEでリファクタリングでき、Java言語自体の型安全性の利点をすべて備えています。

もちろん、特により複雑な結合に関しては、いくつかの欠点もあります。

そのため、一般的に言えば、仕事に最適なツールを使用する必要があります。ほとんどの場合、Criteria APIを使用できますが、レベルを下げる必要がある場合もあります。

5. 結論

この記事では、HibernateおよびJPAの基準クエリの基本、およびAPIの高度な機能のいくつかに注目しました。

ここで説明するコードは、Github repositoryで利用できます。