Overview
このガイドでは、Hibernate ORM 用の MongoDB 拡張機能を使用して、MongoDB コレクションに対して作成、読み取り、更新、および削除する(CRUD)操作を実行する方法を学ぶことができます。
サンプル データ
このガイドの例では、Atlasサンプルデータセットの sample_mflix.moviesコレクションを表す Movie エンティティを使用します。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;
@Entity@Table(name = "movies")public class Movie { @Id @ObjectIdGenerator private ObjectId id; private String title; private String plot; private int year; private List<String> cast; private List<String> directors; private Instant released; @Embedded private Awards awards; @OneToMany(mappedBy = "movie", fetch = FetchType.LAZY) 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 つのエンティティインスタンスのフィールド値を変更し、セッションまたはエンティティ マネージャーを使用して変更を永続化します。
複数のドキュメントを更新: セッション マネージャーまたはエンティティ マネージャーの
createQuery()メソッドまたはcreateMutationQuery()メソッドに更新ステートメントを渡します。次に、executeUpdate()メソッドを呼び出して、変更をデータベースに適用します。
Tip
Hibernate ORM を使用してデータを変更する方法を学ぶには、次のリソースを参照してください。
更新 1 つの例
次の例では、ObjectId 値でドキュメントを検索する。次に、この例ではMovie エンティティの setTitle() メソッドを呼び出して、ドキュメントの title 値を "Jurassic Park I" に更新します。
// Your ObjectId value might differMovie movieById = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));movieById.setTitle("Jurassic Park I");session.persist(movieById);// Your ObjectId value might differMovie 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であるドキュメントのplot値をtitle値と一致するように設定します。
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);条件付きロジックに基づく複数更新の例
次の例では、CASE 式を使用して、各ドキュメントの year 値が 2000 年より後かどうかに応じて plot 値を設定します。Hibernate ORM 拡張機能は、CASE 式を MongoDB $switch 演算子に変換し、$set パイプライン ステージを使用して更新を適用します。
var updateResult = session.createMutationQuery( "update Movie m set m.plot = case when m.year > 2000 then 'Modern release' " + "else 'Classic release' end where m.title = :title") .setParameter("title", "The 3 Stooges") .executeUpdate();System.out.println("Number of movies updated: " + updateResult);CASE 式について詳しく学ぶには、「Specify a クエリ」ガイドの「ユースケース式 for Conditional Logic」セクションをご覧ください。
ドキュメントをアップサートする
アップサート操作は、一致するドキュメントが存在する場合はそのドキュメントを更新し、一致するドキュメントが存在しない場合は新しいドキュメントを挿入します。アップサートを実行するには、upsert()またはupsertMultiple()メソッドを使用します。これらのメソッドは、HibernateのStatelessSession APIでのみ使用できます。
注意
StatelessSession インスタンスは、検索するエンティティへの変更を追跡するしません。エンティティへの変更を保存するには、別の書き込み (write) メソッドに渡します。一括書き込み (write) ワークフローには StatelessSession を使用します。
エンティティの要件
Hibernate ORM拡張機能は、エンティティの識別子からアップサート操作のフィルターを作成するため、upsert()を呼び出す前にアプリケーションで識別子の値を割り当てる必要があります。
upsert() メソッドは、エンティティが @ObjectIdGenerator アノテーションを使用していても、識別子の値を生成しません。識別子値を割り当てない場合、Hibernate ORM 拡張機能は null _id 値でドキュメントを保存します。
@Column(updatable = false) アノテーションを使用すると、アップサート操作中にフィールドが更新されるのを防ぐことができます。次の Movie エンティティ定義では、released フィールドに @Column(updatable = false) をアノテーションとして付与しています。これにより、Hibernate ORM 拡張機能は、ドキュメントを挿入するときにはフィールドに書き込み (write) を行いますが、既存のドキュメントを更新するときにはそのフィールドを省略するようになります。
@Entity@Table(name = "movies")public class Movie { @Id @ObjectIdGenerator private ObjectId id;
private String title; private int year;
@Column(updatable = false) private Instant released;
// Getters and setters omitted}Hibernate ORM 拡張機能は、生成された更新ステートメントの $set 演算子で、挿入可能でも更新可能でもあるフィールドを送信します。それは、@Column(updatable = false) で注釈されたフィールドなどの挿入専用フィールドを $setOnInsert 演算子で送信します。
1つのドキュメントをアップサートする例
次の例では、Movie エンティティ インスタンスを作成し、それを upsert() メソッドに渡します。指定された ObjectId 値を持つドキュメントが存在する場合、Hibernate ORM 拡張機能はそのドキュメントの title 値と year 値を更新します。それ以外の場合、Hibernate 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));}アップサートの制限事項
次のエンティティマッピングは、アップサート操作ではサポートされていません。これらのマッピングのいずれかを使用するエンティティをアップサートすると、Hibernate ORM 拡張機能は FeatureNotSupportedException をスローします。
@Versionでアノテーションが付けられたフィールドを持つエンティティ。@Column(insertable = false)でアノテーションが付けられたフィールドを持つエンティティ。MongoDB クエリ言語には、操作が既存のドキュメントと一致する場合にのみフィールドを書き込み (write) する方法はありません。識別子のみが永続的な属性であるエンティティ。このタイプのエンティティに対するアップサートには更新するフィールドがないため、Hibernate ORM拡張機能は操作を拒否します。
Delete Documents
次の操作を実行して、コレクションからドキュメントを削除することができます。
1つのドキュメントを削除する:セッションマネージャーまたはエンティティマネージャーで、削除するエンティティインスタンスを引数として渡して、
remove()メソッドを呼び出します。複数のドキュメントを削除する: セッション マネージャーまたはエンティティ マネージャーの
createQuery()またはcreateMutationQuery()メソッドに 削除ステートメント を渡します。次に、executeUpdate()メソッドを呼び出して、変更をデータベースに適用します。
Tip
Hibernate ORM を使用してデータを削除する方法の詳細については、次のリソースを参照してください。
削除の例 1 つ
次の例では、ObjectId 値でドキュメントを検索する。次に、この例ではセッションで remove() メソッドを呼び出して、sample_mflix.moviesコレクションから対応するドキュメントを削除します。
// Your ObjectId value might differMovie movieToDelete = session.get(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));session.remove(movieToDelete);// Your ObjectId value might differMovie 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操作を実行する方法の詳細については、次のリソースを参照してください。
作成、読み取り、更新、削除するの例をさらに見るには、「 使い始める 」チュートリアルの次のセクションを参照してください。
Hibernate ORM 拡張機能を使用してクエリを実行する方法の詳細については、次のガイドを参照してください。