Overview
このガイドでは、Hibernate ORM 用の MongoDB 拡張機能を使用して、MongoDB コレクションに対して作成、読み取り、更新、および削除する(CRUD)操作を実行する方法を学ぶことができます。
サンプル データ
このガイドの例では、AtlasサンプルデータセットのMovie sample_mflix.moviesコレクションを表す エンティティを使用します。Movie エンティティには、次の定義があります。
import com.mongodb.hibernate.annotations.ObjectIdGenerator; import org.bson.types.ObjectId; import java.time.Instant; import java.util.List; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; public class Movie { private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; private Awards awards; private List<Comment> comments; public Movie(String title, String plot, int year, List<String> cast, List<String> directors, Instant released, Awards awards) { this.title = title; this.plot = plot; this.year = year; this.cast = cast; this.directors = directors; this.released = released; this.awards = awards; } 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; } public List<String> getDirectors() { return directors; } public void setDirectors(List<String> directors) { this.directors = directors; } public Awards getAwards() { return awards; } public void setAwards(Awards awards) { this.awards = awards; } public Instant getReleased() { return released; } public void setReleased(Instant released) { this.released = released; } public List<Comment> getComments() { return comments; } public void setComments(List<Comment> comments) { this.comments = comments; } }
Hibernetes ORM 用のMongoDB拡張機能を使用してこのMongoDBサンプルコレクションと交流するJavaアプリケーションを作成する方法については、Get Started チュートリアルを参照してください。
重要
永続性コンテキスト
Hibernate ORM を有効にしてデータベースと交流するには、 Hibernate Session または Jakarta Persistence EntityManager を使用して永続性コンテキスト内で操作を実行する必要があります。MongoDBデータを変更し、データの整合性を維持するには、トランザクション内で書き込み (write)操作も実行する必要があります。
このガイドの例を実行する前に、次のコードのような永続性コンテキストとトランザクションマネジメントコードをアプリケーションに追加していることを確認してください。
var sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); // ... Perform CRUD operations here tx.commit(); session.close(); sf.close();
セッションを使用するには、SessionFactory を構成する HibernateUtil.javaファイルを作成する必要があります。詳しく学ぶには、「使い始める」チュートリアルの「アプリケーションを構成する」手順を参照してください。
// 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 を使用するチュートリアルを参照してください。
ドキュメントの挿入
エンティティインスタンスを次のメソッドに渡してドキュメントを作成します。これにより、対応するドキュメントがコレクションに挿入されます。
org.hibernate.Session.persist(): Hibernate APIを使用して変更をデータベースに適用するjakarta.persistence.EntityManager.persist(): Javaリスト 永続化APIを使用して変更をデータベースに適用
Tip
エンティティ インスタンスを作成し、それをデータベースに永続化する方法の詳細については、Hibernate ORM ユーザーガイドの「エンティティの永続化」を参照してください。
例
次の例では、新しい Movie エンティティインスタンスを作成し、persist() メソッドを使用して対応するドキュメントをsample_mflix.moviesコレクションに挿入します。
var myMovie = new Movie(); myMovie.setTitle("Knives Out"); myMovie.setYear(2019); myMovie.setCast(List.of("Ana de Armas", "Daniel Craig", "Chris Evans")); myMovie.setPlot("Detective Benoit Blanc investigates the mysterious death of crime novelist Harlan Thrombey, " + "unraveling lies as every Thrombey family member becomes a suspect."); session.persist(myMovie);
var myMovie = new Movie(); myMovie.setTitle("Knives Out"); myMovie.setYear(2019); myMovie.setCast(List.of("Ana de Armas", "Daniel Craig", "Chris Evans")); myMovie.setPlot("Detective Benoit Blanc investigates the mysterious death of crime novelist Harlan Thrombey, " + "unraveling lies as every Thrombey family member becomes a suspect."); entityManager.persist(myMovie);
ドキュメントを読む
コレクションからドキュメントを検索するには 、クエリ条件を createQuery() メソッドに渡します。次の API は両方とも createQuery() メソッドを提供します。
非表示の
SessionAPI: 非表示クエリ言語(HQL)構文を使用してクエリを定義するJava 永続性の
EntityManagerAPI: クエリを定義するには、HQL のサブセットである Java 永続性クエリ言語(JavaQL)構文 を使用します
Tip
HQL および JQL構文を使用してデータを検索する方法の詳細については、 非表示 ORM クエリガイドの 選択ステートメント を参照してください。
注意
このセクションでは、HQL と JQL を使用してドキュメントを読み取る方法について説明しますが、基準ビルダまたはネイティブ クエリを使用してデータを検索することもできます。詳しくは、次のガイドを参照してください。
1 つのドキュメントの例を返す
クエリ条件に一致するドキュメントを1つだけ検索するには、getSingleResult() メソッドを createQuery() メソッドにチェーンします。次の例では、sample_mflix.moviesコレクションから、title 値が "Boyhood" であるドキュメントを1つ検索します。
var singleResult = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Boyhood") .getSingleResult(); System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
var singleResult = entityManager.createQuery("select m from Movie m where m.title = :t", Movie.class) .setParameter("t", "Boyhood") .getSingleResult(); System.out.println("Title: " + singleResult.getTitle() + ", Year: " + singleResult.getYear());
複数のドキュメントを返す例
次の例では、セッションで createQuery() メソッドを呼び出して、sample_mflix.moviesコレクションからドキュメントを検索します。このコードでは、HQL と JQL を使用して、year の値が 1920 であるドキュメントを返し、その title 値を出力します。
var results = session.createQuery("from Movie where year = :y", Movie.class) .setParameter("y", 1920) .getResultList(); results.forEach(movie -> System.out.println(movie.getTitle()));
var results = entityManager.createQuery("select m from Movie m where m.year = :y", Movie.class) .setParameter("y", 1920) .getResultList(); results.forEach(movie -> System.out.println(movie.getTitle()));
ドキュメントの変更
コレクション内のドキュメントを変更するには、次の操作を実行します。
1 つのドキュメントを更新 : エンティティの setter メソッドを呼び出して 1 つのエンティティインスタンスのフィールド値を変更し、セッションまたはエンティティ マネージャーを使用して変更を永続化します。
Tip
Hibernate ORM を使用してデータを変更する方法を学ぶには、次のリソースを参照してください。
マネージド/永続状態の変更 Hibernate ORM ユーザーガイドの
更新ステートメント Hibernate ORM クエリ ガイド内
更新 1 つの例
次の例では、ObjectId 値でドキュメントを検索する。次に、この例ではMovie エンティティの setTitle() メソッドを呼び出して、ドキュメントの title 値を "Jurassic Park I" に更新します。
// Your ObjectId value might differ Movie movieById = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d")); movieById.setTitle("Jurassic Park I"); session.persist(movieById);
// Your ObjectId value might differ Movie movieById = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d")); movieById.setTitle("Jurassic Park I"); entityManager.persist(movieById);
複数の更新例
次の例では、一致するドキュメントの title の値を "The Three Stooges" から "The 3 Stooges" に更新します。次に、この例ではexecuteUpdate() メソッドを呼び出して、データベースに変更を適用します。
var updateResult = session.createMutationQuery( "update Movie set title = :new where title = :old") .setParameter("new", "The 3 Stooges") .setParameter("old", "The Three Stooges") .executeUpdate(); System.out.println("Number of movies updated: " + updateResult);
var updateResult = entityManager.createQuery( "update Movie m set m.title = :new where m.title = :old") .setParameter("new", "The 3 Stooges") .setParameter("old", "The Three Stooges") .executeUpdate(); System.out.println("Number of movies updated: " + updateResult);
一括更新ステートメントの SET 句では、リテラル値の代わりに式を使用することもできます。式は、アップデートされるフィールドまたはエンティティ上の別のフィールドを参照できます。
次の例では、算術式を使用して、title 値が "The 3 Stooges" であるドキュメントの year 値を増加させます。
var updateResult = session.createMutationQuery( "update Movie m set m.year = m.year + 1 where m.title = :title") .setParameter("title", "The 3 Stooges") .executeUpdate(); System.out.println("Number of movies updated: " + updateResult);
次の例では、フィールド参照を使用して、year の値が 1920 であるドキュメントの title 値と一致するように plot 値を設定します。
var updateResult = session.createMutationQuery( "update Movie m set m.plot = m.title where m.year = :year") .setParameter("year", 1920) .executeUpdate(); System.out.println("Number of movies updated: " + updateResult);
ドキュメントをアップサートする
アップサート操作では、一致するドキュメントが存在する場合はドキュメントが更新され、一致しない場合は新しいドキュメントが挿入されます。アップサートを実行するには、upsert() メソッドまたは upsertMultiple() メソッドを使用します。これらのメソッドは Hibernetes の StatelessSession APIでのみ利用できます。
注意
StatelessSessionインスタンスは、取得するエンティティに対する変更を追跡しません。エンティティへの変更を保存するには、それを別の書込みメソッドに渡します。一括書き込みワークフローには StatelessSession を使用します。
エンティティ要件
Hibernetes ORM 拡張機能は、エンティティの識別子からアップサート操作のフィルターを作成するため、upsert() を呼び出す前にアプリケーションで識別子の値を割り当てる必要があります。
エンティティが @ObjectIdGenerator アノテーションを使用している場合でも、upsert() メソッドは識別子の値を生成しません。識別子値を割り当てない場合、 Hibernetes ORM 拡張機能は null _id 値を持つドキュメントを保存します。
@Column(updatable = false) アノテーションを使用すると、 アップサート操作中にフィールドを更新から保護できます。次の Movie エンティティ定義では、@Column(updatable = false) を使用して releasedフィールドに注釈が付けられています。これは、ドキュメントを挿入するときにフィールドに書込むが、既存のドキュメントを更新するときにフィールドを省略するように Hibernetes ORM 拡張機能に指示します。
public class Movie { private ObjectId id; private String title; private int year; private Instant released; // Getters and setters omitted }
Hibernetes ORM 拡張機能は、生成されたアップデート ステートメントの $set 演算子で挿入可能であり、アップデート可能なフィールドの両方を送信します。 @Column(updatable = false) で注釈が付けられたフィールドなど、挿入可能な専用フィールドを $setOnInsert 演算子で送信します。
アップサートの一例
次の例では、Movie エンティティインスタンスを作成し、それを upsert() メソッドに渡します。指定された ObjectId 値を持つドキュメントが存在する場合、 Hibernetes ORM 拡張機能はそのドキュメントの title 値と year 値を更新します。それ以外の場合、 Hibernetes ORM 拡張機能は新しいドキュメントを挿入します 。
try (StatelessSession statelessSession = sf.openStatelessSession()) { var movie = new Movie(); movie.setId(new ObjectId("573a1398f29313caabce9682")); movie.setTitle("The General"); movie.setYear(1926); movie.setReleased(Instant.parse("1927-02-24T00:00:00Z")); statelessSession.upsert(movie); }
アップサートの複数の例
1 回の操作で複数のエンティティ インスタンスをアップサートするには、 インスタンスのリストを upsertMultiple() メソッドに渡します。次の例では、2 つの Movie エンティティ インスタンスをアップサートします。
try (StatelessSession statelessSession = sf.openStatelessSession()) { var firstMovie = new Movie(); firstMovie.setId(new ObjectId("573a1398f29313caabce9682")); firstMovie.setTitle("The General"); firstMovie.setYear(1926); var secondMovie = new Movie(); secondMovie.setId(new ObjectId("573a1398f29313caabce9683")); secondMovie.setTitle("Metropolis"); secondMovie.setYear(1927); statelessSession.upsertMultiple(List.of(firstMovie, secondMovie)); }
アップサートの制限
次のエンティティマッピングは、アップサート操作ではサポートされていません。これらのマッピングのいずれかを使用するエンティティをアップサートすると、 Hibernetes ORM 拡張機能は FeatureNotSupportedException をスローします。
@Versionで注釈が付けられたフィールドを持つエンティティ。@Column(insertable = false)で注釈が付けられたフィールドを持つエンティティ。 MongoDBクエリ言語では、操作が既存のドキュメントと一致する場合にのみフィールドを書込む方法が提供されません。永続的な属性のみが識別子であるエンティティ。このタイプのエンティティのアップサートでは更新するフィールドがないため、 Hibernetes ORM 拡張機能は操作 を拒否します。
Delete Documents
次の操作を実行して、コレクションからドキュメントを削除することができます。
1 つのドキュメントを削除します :
remove()削除するエンティティインスタンスを引数として渡して、セッション マネージャーまたはエンティティ マネージャーで メソッドを呼び出します。
Tip
Hibernate ORM を使用してデータを削除する方法の詳細については、次のリソースを参照してください。
エンティティを削除する Hibernate ORM ユーザー ガイドの
削除するステートメント Hibernate ORM クエリ ガイドの
削除の例 1 つ
次の例では、ObjectId 値でドキュメントを検索する。次に、この例ではセッションで remove() メソッドを呼び出して、sample_mflix.moviesコレクションから対応するドキュメントを削除します。
// Your ObjectId value might differ Movie movieToDelete = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d")); session.remove(movieToDelete);
// Your ObjectId value might differ Movie movieToDelete = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d")); entityManager.remove(movieToDelete);
削除の複数の例
次の例では、sample_mflix.moviesコレクションから year 値が 1920 であるすべてのドキュメントを削除します。この例ではステートメントを削除するために createMutationQuery() メソッドに渡し、executeUpdate() メソッドを呼び出してデータベースに変更を適用します。
var deleteResult = session.createMutationQuery( "delete Movie where year = :y") .setParameter("y", 1920) .executeUpdate(); System.out.println("Number of movies deleted: " + deleteResult);
var deleteResult = entityManager.createQuery( "delete Movie m where m.year = :y") .setParameter("y", 1920) .executeUpdate(); System.out.println("Number of movies deleted: " + deleteResult);
詳細情報
Hibernate ORM を使用してCRUD操作を実行する方法の詳細については、次のリソースを参照してください。
Persistence Context Hibernate ORM ユーザー ガイドの
ステートメント タイプ Hibernate ORM クエリ ガイドにおける
作成、読み取り、更新、削除するの例をさらに見るには、「 使い始める 」チュートリアルの次のセクションを参照してください。
Hibernate ORM 拡張機能を使用してクエリを実行する方法の詳細については、次のガイドを参照してください。