JPAクエリのタイプ

1. 概要

このチュートリアルでは、さまざまなタイプのlink:/jpa-hibernate-difference[JPA]クエリについて説明します。 さらに、それらの違いを比較し、それぞれの長所と短所を拡大することに焦点を当てます。

2. セットアップ

まず、この記事のすべての例で使用する_UserEntity_クラスを定義しましょう。
@Table(name = "users")
@Entity
public class UserEntity {

    @Id
    private Long id;
    private String name;
    //Standard constructor, getters and setters.

}
  • JPAクエリには3つの基本タイプがあります:*

  • Query、Java Persistence Query Language(JPQL)構文で記述

  • NativeQuery、プレーンSQL構文で記述

  • Criteria API Query、異なる方法でプログラムで構築
    方法

    それらを探検しましょう。

3. クエリ

  • _Query_はSQLと構文が似ており、一般的にCRUD操作を実行するために使用されます:*

public UserEntity getUserByIdWithPlainQuery(Long id) {
    Query jpqlQuery = getEntityManager().createQuery("SELECT u FROM UserEntity u WHERE u.id=:id");
    jpqlQuery.setParameter("id", id);
    return (UserEntity) jpqlQuery.getSingleResult();
}
この_Query_は、_users_テーブルから一致するレコードを取得し、_UserEntity_オブジェクトにマップします。
2つの追加の_Query_サブタイプがあります。
  • TypedQuery

  • NamedQuery

    実際にそれらを見てみましょう。

* 3.1。 TypedQuery *

前の例の_return_ステートメントに注意する必要があります。 JPAは_Query_結果タイプが何であるかを推測できず、結果としてキャストする必要があります。
ただし、* JPAはa__TypedQuery ._ *と呼ばれる特別な_Query_サブタイプを提供します。これは、_Query_結果タイプを事前に知っている場合は常に推奨されます。 さらに、コードの信頼性が高まり、テストが容易になります。
最初の例と比較して、_TypedQuery_の代替案を見てみましょう。
public UserEntity getUserByIdWithTypedQuery(Long id) {
    TypedQuery<UserEntity> typedQuery
      = getEntityManager().createQuery("SELECT u FROM UserEntity u WHERE u.id=:id", UserEntity.class);
    typedQuery.setParameter("id", id);
    return typedQuery.getSingleResult();
}
このように、*無料で強力なタイピングを取得*し、将来のキャスト例外の可能性を回避します。

* 3.2。 NamedQuery *

特定のメソッドで_Query_を動的に定義することはできますが、最終的にはメンテナンスが困難なコードベースに成長する可能性があります。 一般的な使用法のクエリを、一元化された読みやすい場所に保管できたらどうでしょうか
JPAは、a__https://www.baeldung.com/hibernate-named-query [NamedQuery] ._として知られる別の_Query_サブタイプでこれについても説明しました。
  • _Entity_クラス自体に_NamedQuery_を定義し、_Entity_の関連クエリを一元化してすばやく簡単に読み取って検索できるようにします。*

    すべての_NamedQueries_には一意の名前が必要です。
    _NamedQuery_を_UserEntity_クラスに追加する方法を見てみましょう。
@Table(name = "users")
@Entity
@NamedQuery(name = "UserEntity.findByUserId", query = "SELECT u FROM UserEntity u WHERE u.id=:userId")
public class UserEntity {

    @Id
    private Long id;
    private String name;
    //Standard constructor, getters and setters.

}
*バージョン8より前のJavaを使用している場合は、_ @ NamedQuery_アノテーションを_ @ NamedQueries_アノテーション内にグループ化する必要があります。 Java 8以降では、_Entity_クラスで_ @ NamedQuery_アノテーションを繰り返すだけです。*
_NamedQuery_の使用は非常に簡単です。
public UserEntity getUserByIdWithNamedQuery(Long id) {
    Query namedQuery = getEntityManager().createNamedQuery("UserEntity.findByUserId");
    namedQuery.setParameter("userId", id);
    return (UserEntity) namedQuery.getSingleResult();
}

4. NativeQuery

  • _NativeQuery_は単なるSQLクエリです。 これらにより、JPQL制限構文では利用できない独自の機能を使用できるため、データベースの能力を最大限に活用できます。*

    これにはコストがかかります。 JPAプロバイダーはデータベースの実装またはベンダーから特定の詳細を抽象化できないため、_NativeQuery_を使用してアプリケーションのデータベースの移植性を失います。
    前の例と同じ結果が得られる_NativeQuery_の使用方法を見てみましょう。
public UserEntity getUserByIdWithNativeQuery(Long id) {
    Query nativeQuery
      = getEntityManager().createNativeQuery("SELECT * FROM users WHERE id=:userId", UserEntity.class);
    nativeQuery.setParameter("userId", id);
    return (UserEntity) nativeQuery.getSingleResult();
}
_NativeQuery_が唯一のオプションであるかどうかを常に考慮する必要があります。 *ほとんどの場合、優れたJPQL _Query_は私たちのニーズを満たすことができ、最も重要なことは、実際のデータベース実装からの抽象化レベルを維持することです。*
_NativeQuery_を使用することは、特定のデータベースベンダーにロックすることを必ずしも意味しません。 結局、クエリが独自のSQLコマンドを使用せず、標準のSQL構文のみを使用している場合、プロバイダーの切り替えは問題になりません。

5. * Criteria APIクエリ*

  • https://www.baeldung.com/hibernate-criteria-queries [Criteria APIクエリ]は、プログラムで構築されたタイプセーフクエリです。構文はJPQLクエリに多少似ています:*

public UserEntity getUserByIdWithCriteriaQuery(Long id) {
    CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
    CriteriaQuery<UserEntity> criteriaQuery = criteriaBuilder.createQuery(UserEntity.class);
    Root<UserEntity> userRoot = criteriaQuery.from(UserEntity.class);
    UserEntity queryResult = getEntityManager().createQuery(criteriaQuery.select(userRoot)
      .where(criteriaBuilder.equal(userRoot.get("id"), id)))
      .getSingleResult();
    return queryResult;
}
_Criteria_ APIクエリを直接使用するのは困難な場合がありますが、動的クエリ要素を追加する必要がある場合、またはlink:/hibernate-criteria-queries-metamodelと組み合わせる場合に最適な選択肢になる可能性があります[JPA _メタモデル_。]

6. 結論

この簡単な記事では、JPAクエリの概要とその使用方法を学びました。
JPAクエリは、JPQL構文に依存し、JPAプロバイダーが_Query_変換を処理できるようにするため、ビジネスロジックをデータアクセスレイヤーから抽象化する優れた方法です。
この記事で紹介するすべてのコードは、https://github.com/eugenp/tutorials/tree/master/persistence-modules/java-jpa [GitHub上]で入手できます。