Overview
このガイドでは、Hibernate ORM 用の MongoDB 拡張機能を使用してデータベースクエリを指定する方法を学習します。
クエリフィルターを作成することで、クエリが返すドキュメントのセットを絞り込むことができます。クエリフィルターは、 MongoDB が読み取りまたは書込み (write)操作においてドキュメントを照合するために使用する検索条件を指定する式です。 MongoDBクエリフィルターを作成するには、 非表示クエリ言語(HQL) または Java 永続クエリ言語(JQL) ステートメントを使用します。
Tip
HQL と JQL の構文 の詳細については、非表示の ORM ドキュメントの 非表示のクエリ言語に関するガイド を参照してください。
注意
クエリ サポート
Hibernate ORM 用のMongoDB拡張機能は、すべてのMongoDBおよびHibernateのクエリ機能をサポートしていません。詳しくは、機能の互換性ページでクエリ サポートを参照してください。
サンプル データ
このガイドの例では、Atlasサンプルデータセットの sample_mflix.moviesコレクションを表す Movie エンティティを使用します。Movie エンティティには次の定義があります。
import com.mongodb.hibernate.annotations.ObjectIdGenerator; import org.bson.types.ObjectId; import java.util.List; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; public Movie(String title, String plot, int year, List<String> cast) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; } public Movie() { } public ObjectId getId() { return id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getPlot() { return plot; } public void setPlot(String plot) { this.plot = plot; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public List<String> getCast() { return cast; } public void setCast(List<String> cast) { this.cast = cast; } }
Hibernetes ORM 用のMongoDB拡張機能 を使用してこのMongoDBサンプルコレクションを操作するJavaアプリケーションを作成する方法については、「 開始 」チュートリアルを参照してください。
重要
永続性コンテキスト
Hibernetes ORM を有効にしてデータベースを操作するには、 Hibernetes Session または Java 永続性 EntityManager を使用して永続性コンテキスト内で操作を実行する必要があります。セッション クエリを定義するには HQL を使用し、エンティティ マネージャー クエリを定義するには JQL を使用します。
このガイドの例を実行する前に、次のコードのような永続性コンテキストとトランザクションマネジメントコードをアプリケーションに追加していることを確認してください。
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); // ... Perform CRUD operations here tx.commit(); session.close(); sf.close();
セッションを使用するには、HibernateUtil.java を構成するSessionFactory ファイルを作成する必要があります。詳細については、「 使い始める 」チュートリアルの「 アプリケーションを構成する 」の手順を参照してください。
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml file EntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>"); EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); // ... Perform CRUD operations here entityManager.getTransaction().commit(); entityManager.close(); emf.close;
EntityManager を使用するには、永続性ユニットを宣言する persistence.xmlファイルを作成する必要があります。詳細を学ぶには、Hibernate ORM ドキュメントのJPA 標準 API を使用するチュートリアルを参照してください。
クエリの実行
MongoDBデータをクエリするには、セッションまたはエンティティ マネージャーで createQuery() メソッドを呼び出します。次に、非表示クエリ言語(HQL)または Java 永続クエリ言語(JQL)のステートメントで一致する条件を指定します。
このセクションでは、次のクエリ操作を実行する方法について説明します。
すべてのドキュメントを検索する
コレクションからすべてのドキュメントを検索するには、基本的な 選択ステートメント を createQuery() メソッドに渡します。このステートメントでは、クエリするコレクションを表すエンティティを指定します。
次の例では、Movie エンティティをクエリして、sample_mflix.moviesコレクションからすべてのドキュメントの title 値を検索します。
var allDocs = session.createQuery("select title from Movie", String.class) .getResultList(); for (var t : allDocs) { System.out.println("Title: " + t); }
Title: A Corner in Wheat Title: Gertie the Dinosaur Title: The Perils of Pauline Title: Civilization Title: Where Are My Children? ...
var allDocs = entityManager.createQuery("select m.title from Movie m", String.class) .getResultList(); for (var t : allDocs) { System.out.println("Title: " + t); }
Title: A Corner in Wheat Title: Gertie the Dinosaur Title: The Perils of Pauline Title: Civilization Title: Where Are My Children? ...
一致するドキュメントの取得
特定の条件に一致するドキュメントを検索するには、where 句を含む選択ステートメントを createQuery() メソッドに渡します。このステートメントでは、クエリするコレクションと一致する条件を表すエンティティを指定します。
次の例では、sample_mflix.moviesコレクションから、title 値が "Romeo and Juliet" であるドキュメントを検索します。
var matchingDocs = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Romeo and Juliet") .getResultList(); for (var m : matchingDocs) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Romeo and Juliet, Year: 1936 Title: Romeo and Juliet, Year: 1968
var matchingDocs = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class) .setParameter("t", "Romeo and Juliet") .getResultList(); for (var m : matchingDocs) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Romeo and Juliet, Year: 1936 Title: Romeo and Juliet, Year: 1968
Retrieve One Document
特定の条件に一致する単一のドキュメントを検索するには、getSingleResult() メソッドを createQuery() メソッドにチェーンします。
次の例では、sample_mflix.moviesコレクションから、title 値が "Best in Show" である単一のドキュメントを検索します。
var singleResult = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Best in Show") .getSingleResult(); System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
Title: Best in Show, Year: 2000
var singleResult = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class) .setParameter("t", "Best in Show") .getSingleResult(); System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
Title: Best in Show, Year: 2000
重要
nonUniqueResultException エラー
クエリが複数のドキュメントに一致する場合、getSingleResult() メソッドはNonUniqueResultException エラーをスローします。このエラーを回避するには、クエリが 1 つのドキュメントのみと一致することを確認するか、クエリ結果を 1 つのドキュメントに制限します。
Criteria APIクエリの実行
HQL または JQL ステートメントを使用してクエリフィルターを作成する代わりに、Java 永続化基準API を使用して型安全性のあるクエリをプログラムで構築できます。
Criteria APIを使用してクエリを作成するには、次のアクションを実行します。
セッションまたはエンティティ マネージャーから
CriteriaBuilderオブジェクトを作成します。ビルダから
CriteriaQueryオブジェクトを作成し、クエリするエンティティを指定します。クエリ条件を指定するには、
CriteriaQueryクラスが提供するクエリメソッドを使用します。
Tip
Criteria APIの詳細については、Java JIRA ドキュメントの「 Criteria API を使用してクエリを作成する 」を参照してください。
次の例では、Criteria APIを使用して、sample_mflix.moviesコレクションから year 値が 1925 であるすべてのドキュメントを検索する。
CriteriaBuilder cb = session.getCriteriaBuilder(); CriteriaQuery<Movie> cq = cb.createQuery(Movie.class); Root<Movie> movieRoot = cq.from(Movie.class); cq.select(movieRoot).where(cb.equal(movieRoot.get("year"), 1925)); session.createQuery(cq).getResultList() .forEach(m -> System.out.println(m.getTitle()));
Lady Windermere's Fan Clash of the Wolves Grass: A Nation's Battle for Life
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Movie> cq = cb.createQuery(Movie.class); Root<Movie> movieRoot = cq.from(Movie.class); cq.select(movieRoot).where(cb.equal(movieRoot.get("year"), 1925)); entityManager.createQuery(cq).getResultList() .forEach(m -> System.out.println(m.getTitle()));
Lady Windermere's Fan Clash of the Wolves Grass: A Nation's Battle for Life
ネイティブクエリを実行する
現在 Hibernate ORM 拡張機能でサポートされていないMongoDBクエリを実行するには、クエリをMongoDBクエリ言語(MQL)ステートメントとして createNativeQuery() メソッドに渡します。
クエリフィルターをカスタマイズする
このセクションでは、演算子を使用して次のタイプのクエリフィルターを作成する方法について説明します。
Tip
このセクションでは、使用可能なすべてのクエリ演算子について説明するわけではありません。クエリ演算子の完全なリストを表示するには、 Hibernetes ORM クエリガイドの「 演算子式 」を参照してください。
比較フィルターの使用
注意
Hibernetes ORM 拡張機能は、LIKE やBETWEEN を含むすべての比較演算子をサポートしていません。サポート制限の詳細については、 機能の互換性 ページの 「クエリ サポート」 を参照してください。
クエリ ステートメントで次の演算子を使用して、フィールド値を指定されたクエリ値と比較できます。
=: 等価一致<>: 等価一致>: 比較より大きい>=: 以上の比較<: 比較より小さい<=: 以下の比較
次の例では、sample_mflix.moviesコレクションから、year の値が 2015 以上であるドキュメントを検索します。
var comparisonResult = session.createQuery("from Movie where year >= :y", Movie.class) .setParameter("y", 2015) .getResultList(); for (var m : comparisonResult) { System.out.println("Title: " + m.getTitle()); }
Title: Jurassic World Title: The Stanford Prison Experiment Title: Ex Machina Title: Ant-Man Title: The Danish Girl Title: The Wedding Ringer Title: Good Ol' Boy Title: A Tale of Love and Darkness Title: Aloha ...
var comparisonResult = entityManager.createQuery("select m from Movie m where m.year >= :y", Movie.class) .setParameter("y", 2015) .getResultList(); for (var m : comparisonResult) { System.out.println("Title: " + m.getTitle()); }
Title: Jurassic World Title: The Stanford Prison Experiment Title: Ex Machina Title: Ant-Man Title: The Danish Girl Title: The Wedding Ringer Title: Good Ol' Boy Title: A Tale of Love and Darkness Title: Aloha ...
論理フィルターの使用
クエリ ステートメントでは次の演算子を使用して、複数のクエリ条件を組み合わせることができます。
and: すべての条件に一致するor: 任意の条件に一致しますnot: Invert criteria
次の例では、 sample_mflix.moviesコレクションから、title 値が "The Godfather" で、かつ year 値が 1972 であるドキュメントを検索します。
var logicalResult = session.createQuery("from Movie where title = :t and year = :y", Movie.class) .setParameter("t", "The Godfather") .setParameter("y", 1972) .getSingleResult(); System.out.println("Title: " + logicalResult.getTitle());
Title: The Godfather
var logicalResult = entityManager.createQuery("select m from Movie m where m.title = :t and m.year = :y", Movie.class) .setParameter("t", "The Godfather") .setParameter("y", 1972) .getSingleResult(); System.out.println("Title: " + logicalResult.getTitle());
Title: The Godfather
クエリ結果の変更
このセクションでは、クエリ結果を次の方法で変更する方法について説明します。
結果を並べ替える
クエリ ステートメントで order by 句を使用すると、指定したフィールドの値でクエリ結果をソートできます。デフォルトでは 、order by 句はドキュメントを昇順でソートします。ドキュメントを降順で並べ替えるには、フィールド名に desc キーワードを追加します。
次の例では、sample_mflix.moviesコレクションから一致するドキュメントを検索し、yearフィールドで降順に並べ替えます。
var sortResult = session.createQuery("from Movie where title = :t order by year desc", Movie.class) .setParameter("t", "Cinderella") .getResultList(); for (var m : sortResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
var sortResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc", Movie.class) .setParameter("t", "Cinderella") .getResultList(); for (var m : sortResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
結果をスキップする
setFirstResult() メソッドをクエリに連結することで、クエリ結果内の指定した数のドキュメントをスキップできます。スキップする初期ドキュメントの数をこのメソッドの引数として渡します。
次の例では、前の例と同じクエリを実行しますが、結果内の最初の一致するドキュメントをスキップします。
var skipResult = session.createQuery("from Movie where title = :t order by year desc", Movie.class) .setParameter("t", "Cinderella") .setFirstResult(1) .getResultList(); for (var m : skipResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
var skipResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc", Movie.class) .setParameter("t", "Cinderella") .setFirstResult(1) .getResultList(); for (var m : skipResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 1997 Title: Cinderella, Year: 1950
結果を制限する
クエリが返すドキュメント数を制限するには、setMaxResults() メソッドをクエリに連結します。返されるドキュメントの最大数をこのメソッドの引数として渡します。
次の例では、ソートの例と同じクエリを実行しますが、結果には一致するドキュメントが最大 2 つ返されます。
var limitResult = session.createQuery("from Movie where title = :t order by year desc", Movie.class) .setParameter("t", "Cinderella") .setMaxResults(2) .getResultList(); for (var m : limitResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997
var limitResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc", Movie.class) .setParameter("t", "Cinderella") .setMaxResults(2) .getResultList(); for (var m : limitResult) { System.out.println("Title: " + m.getTitle() + ", Year: " + m.getYear()); }
Title: Cinderella, Year: 2015 Title: Cinderella, Year: 1997
あるいは、次のコードに示すように、HQL または JQL のステートメントで limit 句を使用して、クエリが返すドキュメントの数を制限することもできます。
var limitClauseResult = session.createQuery("from Movie where title = :t order by year desc limit 2", Movie.class) .setParameter("t", "Cinderella") .getResultList();
var limitClauseResult = entityManager.createQuery("select m from Movie m where m.title = :t order by m.year desc limit 2", Movie.class) .setParameter("t", "Cinderella") .getResultList();
高度なフィールドクエリ
このセクションでは、次のフィールドでクエリを実行する方法について説明します。
プライマリキー フィールドのクエリ
ObjectId 値に基づいてドキュメントを検索するには、セッションを使用している場合はこの値を get() メソッドに渡します。また、エンティティ マネージャーを使用している場合は find() メソッドに引数として渡します。 。
次の例では、sample_mflix.moviesコレクションからドキュメントをObjectId値で検索する。
var movieById = session.get(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
var movieById = entityManager.find(Movie.class, new ObjectId("573a13a8f29313caabd1d53c"));
埋め込みフィールドのクエリ
MongoDB埋め込みドキュメントを表現するには、@Struct 集計埋め込み可能ファイルを作成します。埋め込み可能な個々の値にクエリフィルターを作成することはできませんが、 Hibernetes ORM 拡張機能を使用して特定の親エンティティに関連付けられている @Struct 集計埋め込み可能値を取得できます。
Tip
埋め込みドキュメントの表現の詳細については、 エンティティの作成ガイドの「埋め込みデータ」を参照してください。
次の例では、sample_mflix.moviesコレクションから title 値が "Hairspray" であるドキュメントを検索します。次に、コードは Awards @Struct 集計埋め込み可能を保存する awardsフィールドを取得し、Awards 埋め込み可能型の winsフィールドを出力します。
var embeddedResult = session.createQuery("select awards from Movie where title = :title", Awards.class) .setParameter("title", "Hairspray") .getResultList(); for (var a : embeddedResult) { System.out.println("Award wins: " + a.getWins()); }
Award wins: 0 Award wins: 21
var embeddedResult = entityManager.createQuery("select m.awards from Movie m where m.title = :title", Awards.class) .setParameter("title", "Hairspray") .getResultList(); for (var a : embeddedResult) { System.out.println("Award wins: " + a.getWins()); }
Award wins: 0 Award wins: 21
配列フィールドのクエリ
Hibernetes ORM 拡張機能は、配列フィールドをクエリするための次の関数をサポートしています。
array_contains(): 配列フィールドに指定された値が含まれるドキュメントの一致array_contains_nullable(): 配列フィールドにnull値を含む指定された値が含まれるドキュメントの一致array_includes(): 配列フィールドに別の配列値が含まれるドキュメントの一致array_includes_nullable(): 配列フィールドに、null値を含む別の配列値が含まれるドキュメントの一致
Tip
配列関数の詳細については、 Hibernetes ORM ユーザーガイドの 配列を処理するための関数 を参照してください。
次の例では、array_contains() 関数を使用して、sample_mflix.moviesコレクションから cast 配列フィールドに値 "Kathryn Hahn" を持つドキュメントを検索する。
var arrayResult = session.createQuery("from Movie where array_contains(cast, :actor)", Movie.class) .setParameter("actor", "Kathryn Hahn") .getResultList(); for (var m : arrayResult) { System.out.println("Title: " + m.getTitle()); }
Title: How to Lose a Guy in 10 Days Title: The Secret Life of Walter Mitty Title: Bad Words Title: Afternoon Delight Title: The D Train
var arrayResult = entityManager.createQuery("select m from Movie m where array_contains(m.cast, :actor)", Movie.class) .setParameter("actor", "Kathryn Hahn") .getResultList(); for (var m : arrayResult) { System.out.println("Title: " + m.getTitle()); }
Title: How to Lose a Guy in 10 Days Title: The Secret Life of Walter Mitty Title: Bad Words Title: Afternoon Delight Title: The D Train
詳細情報
MongoDBデータに対してその他の操作を行う方法の詳細については、CRUD 操作ガイドを参照してください。
HQL と JQL を使用してクエリを実行する方法の詳細については、非表示の ORM ドキュメントの「 非表示のクエリ言語へのガイド 」を参照してください。