Overview
このガイドでは、Hibernate ORM 用の MongoDB 拡張機能を使用してトランザクションを実行する方法を学ぶことができます。トランザクションを使用すると、トランザクション全体がコミットされた場合にのみデータを変更する一連の操作を実行できます。
MongoDBでは、トランザクションは論理セッション内で実行されます。セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。セッションにより、一連の操作に対する 因果整合性 が有効になり、ACID準拠のトランザクション内で操作を実行できるようになります。これは、アトミック性、整合性、分離、 耐久性 の期待を満たすトランザクションです。
Hibernetes ORM 拡張機能は、セッションとトランザクションを管理するための次の API をサポートしています。
Sessionを非表示:org.hibernate.TransactionAPIを使用してデータベース操作をグループ化できます。詳細については、書き込み ORM ユーザーガイドの 非表示トランザクションAPI を参照してください。Jakarta Persistence
EntityManager: Hibernate ORM にSessionをマネージドで内部的に管理するように指示し、jakarta.persistence.EntityTransactionAPI を使用してデータベース操作をグループ化できるようにします。詳細については、Java EA ドキュメントのjavarta.persistencyパッケージを参照してください。
サンプル データ
このガイドの例では、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 チュートリアルを参照してください。
セッションを作成
MongoDBデータと交流するには、すべてのデータベース操作をセッション内で実行する必要があります。このセクションでは、データベースセッションを次の方法で管理する方法を説明します。
非表示セッションを使用する: 非表示のネイティブAPIを使用して、
SessionFactoryからSessionを作成しますJPA EntityManager を使用する: Javaリスト永続化APIを使用して
EntityManagerFactoryからEntityManagerを作成します
一時停止セッションの使用
Tip
Session を使用する前に、SessionFactory を構成する HibernateUtil.javaファイルを作成する必要があります。学ぶには、「使い始める」チュートリアルの「アプリケーションを構成する」手順を参照してください。
非表示 Session を起動するには、次の手順を実行します。
getSessionFactory()メソッドを使用して、HibernateUtilユーティリティクラスからSessionFactoryを検索します。SessionFactoryはMongoDB接続構成を保存し、新しいデータベースセッションを開くことができます。SessionFactoryインスタンスでopenSession()メソッドを呼び出してSessionを作成します。データベース操作を実行中したら、両方のインスタンスで
close()メソッドを使用してSessionFactoryとSessionを閉じます。
次の例では、データベースクエリをセッションで実行し、sample_mflix.moviesコレクションからtitle値が"Erin Brockovich"であるドキュメントを検索します。
var sf = HibernateUtil.getSessionFactory();Session session = sf.openSession();
var movie = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Erin Brockovich") .getSingleResult();System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear());
session.close();sf.close();次のコードに示すように、Java の try-with-resources ステートメント を使用してセッション管理ロジックを簡素化し、セッションを自動的に閉じることもできます。
var sf = HibernateUtil.getSessionFactory();try (Session session = sf.openSession()) { var movie = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Erin Brockovich") .getSingleResult(); System.out.println("Title: " + movie.getTitle() + ", Year: " + movie.getYear());}sf.close();JPA EntityManager の使用
Tip
EntityManager を使用する前に、永続性ユニットを宣言する persistence.xmlファイルを作成する必要があります。詳細を学ぶには、Hibernate ORM ドキュメントのJPA 標準 API を使用するチュートリアルを参照してください。
Jakarta 永続化API(JPA)EntityManager を起動するには、次の手順を実行します。
createEntityManagerFactory()メソッドを呼び出して、persistence.xmlファイルからEntityManagerFactoryを作成します。これにより、内部的にSessionFactoryが作成されます。EntityManagerFactoryインスタンスでcreateEntityManager()メソッドを呼び出してEntityManagerを作成します。これにより、内部的にSessionが作成されます。データベース操作を実行中したら、両方のインスタンスで
close()メソッドを呼び出して、EntityManagerFactoryとEntityManagerを閉じます。
次の例では、エンティティ マネージャーでデータベースクエリを実行し、sample_mflix.moviesコレクションから year 値が 1929 であるドキュメントを検索します。
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml fileEntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>");EntityManager entityManager = emf.createEntityManager();
var results = entityManager.createQuery("select m from Movie m where m.year = :y", Movie.class) .setParameter("y", 1929) .getResultList();results.forEach(movie -> System.out.println(movie.getTitle()));
entityManager.close();emf.close();Java の永続性3.1 v 以降では、EntityManager 非表示のセッション のセクションに示されているように、Java のtry-with-resources ステートメントを使用して を自動的に閉じることができます。
トランザクションの実行
MongoDBデータを変更するには、トランザクション内ですべての書き込み操作を実行する必要があります。このセクションでは、次の方法でトランザクションをマネージドする方法を説明します。
非表示トランザクションを使用する: 非表示のネイティブ
org.hibernate.TransactionAPIを使用して、Sessionからトランザクションを開始しますJPA EntityTransaction を使用する:
jakarta.persistence.EntityTransactionAPIを使用して、EntityManagerからトランザクションを開始します
一時停止トランザクションの使用
非表示 Transaction を起動するには、Sessionインスタンスで beginTransaction() メソッドを呼び出します。操作を実行し、persist() メソッドを使用して変更をセッションに登録した後、commit() メソッドを呼び出してトランザクションをコミットします。
次の例では、トランザクションを使用して、sample_mflix.moviesコレクションに対して次の操作を実行しています。
新しい
Movieエンティティを作成し、それをドキュメントとしてコレクションに挿入しますtitleの値が"Black Swan"であるドキュメントのcastフィールドを更新します
強調表示された行はトランザクションを開始し、コミットします。
var sf = HibernateUtil.getSessionFactory();Session session = sf.openSession();Transaction tx = session.beginTransaction();
var newMovie = new Movie();newMovie.setTitle("Lady Bird");newMovie.setYear(2017);session.persist(newMovie);
var movie = session.createQuery("from Movie where title = :t", Movie.class) .setParameter("t", "Black Swan") .getSingleResult();var currentCast = new ArrayList<>(movie.getCast());currentCast.add("Winona Ryder");movie.setCast(currentCast);
tx.commit();session.close();sf.close();JPA EntityTransaction の使用
JPA EntityTransaction を作成するには、EntityManager で getTransaction() メソッドを呼び出します。このメソッドでは、基礎の Hibernate Transaction をラップする EntityTransaction が検索されます。次に、begin() メソッドを呼び出してトランザクションを開始します。操作を実行し、persist() メソッドを使用してエンティティ マネージャーに変更を登録した後、commit() メソッドを呼び出してトランザクションをコミットします。
次の例では、EntityTransaction を使用して sample_mflix.moviesコレクションからドキュメントを削除し、タイトル値が "The Favourite" である新しいドキュメントを挿入します。強調表示された行はトランザクションを開始し、コミットします。
// Replace <persistence unit> with the name of your persistence unit in the persistence.xml fileEntityManagerFactory emf = Persistence.createEntityManagerFactory("<persistence unit>");EntityManager entityManager = emf.createEntityManager();entityManager.getTransaction().begin();
// Your ObjectId value might differMovie movieToDelete = entityManager.find(Movie.class, new ObjectId("573a1399f29313caabcedc5d"));entityManager.remove(movieToDelete);
var addMovie = new Movie();addMovie.setTitle("The Favourite");addMovie.setYear(2018);entityManager.persist(addMovie);
entityManager.getTransaction().commit();entityManager.close();emf.close();トランザクションエラーの処理
トランザクションからすべてのデータ変更を破棄するには、 Hibernetes Transaction または JPA EntityTransaction で rollback() メソッドを呼び出します。このメソッドを呼び出した後、非表示 ORM はコミットされていない変更を元に戻し、永続性コンテキストをクリアします。
次の例では、コードがエラーをスローした場合にトランザクションをロールバックします。対応するコードを表示するには、Hibernate Transaction タブまたは JPA EntityTransactionタブを選択します。
Session session = sessionFactory.openSession();Transaction tx = null;
try { tx = session.beginTransaction();
Movie movie = new Movie(); movie.setTitle("Control Alt Delete"); session.persist(movie);
tx.commit();} catch (Exception e) { if (tx != null) { tx.rollback(); } e.printStackTrace();} finally { session.close();}EntityManager entityManager = emf.createEntityManager();EntityTransaction tx = entityManager.getTransaction();
try { tx.begin();
Movie movie = new Movie(); movie.setTitle("Control Alt Delete"); entityManager.persist(movie);
tx.commit();} catch (Exception e) { if (tx != null && tx.isActive()) { tx.rollback(); } e.printStackTrace();} finally { entityManager.close();}詳細情報
セッションとエンティティ マネージャーの詳細については、Hibernate ORM ドキュメントの永続性コンテキストを参照してください。
トランザクションの詳細を学ぶには、 Hibernate ORM ドキュメントの「トランザクション」を参照してください。