Overview
このチュートリアルでは、アトミック性、整合性、分離、 耐久性 (ACID)の保証を満たすマルチドキュメントトランザクションを実行する方法を学習できます。
すべてのMongoDB Serverバージョンは単一ドキュメントトランザクションをサポートし、トランザクション内でドキュメントに対して複数のアップデートを実行する場合はACIDコンプライアンスを保証します。 MongoDB Server v4.0 以降では、複数のドキュメント、コレクション、データベースにわたってACID準拠のトランザクションを実行できます。
Tutorial
このチュートリアルでは、製品の在庫と購入データのマルチドキュメントトランザクションを実行する 例アプリケーション をダウンロードする方法を説明します。チュートリアルでは、例アプリケーションのtransactions ディレクトリにある次のファイルを使用します。
Transactions.java:cartとproductコレクションにアクセスし、両方のコレクションに対して操作を実行して、ファイルの購入を反映します。このコードは、アプローチを比較するために、 ACIDトランザクション 内でトランザクションなしで動作します。ChangeStreams.java:cartコレクションとproductコレクションのデータ変更に関する情報を返します。models/Cart.java: コレクション内のドキュメントに対応する、買い物かごを表す POJOクラス。cartmodels/Product.java:productコレクション内のドキュメントに対応する、1 つのアイテムとその在庫を表す POJOクラス。
前提条件を確認します。
このチュートリアルを開始する前に、次のコンポーネントが準備されていることを確認してください。
構成されたクラスターを持つMongoDB Atlasアカウント。クラスターの作成方法については、 「MongoDBスタートガイド」をご覧ください。
Javaドライバー v5.0 以降。
Java 21 以降。
Maven v3.8.7 以降。
変更ストリームを開始し、コレクションを構成します。
コレクションと コレクションを作成し、 JSON スキーマを構成するには、cart productChangeStreams.javaファイルを実行します。 java-quick-startディレクトリに移動し、次のコマンドを実行します。
mvn compile exec:java \ -Dexec.mainClass="com.mongodb.quickstart.transactions.ChangeStreams" \ -Dmongodb.uri="<connection URI>"
Tip
<connection URI> プレースホルダーをクラスターの接続 URI に置き換えます。
このファイルは、次のアクションを実行します。
testデータベースにcartコレクションを作成します。testデータベースにproductコレクションを作成します。ドキュメントフィールドにデータ型と値の制約を設定する
productコレクションにJSONスキーマを適用します。このスキーマでは、stockフィールドの値が0以上に維持されます。これにより、在庫なしのアイテムを購入しようとするトランザクションはエラーがスローされ、成功しません。変更ストリームを開き、
testデータベースへの変更をモニタリングします。
サンプルデータを挿入してデータ操作を開始します。
ミリ秒は、ファイルを購入したいサンプルカスタマーです。 Transactions.javaファイルは、の購入を反映するためにデータベース操作を実行します。このプログラムを起動するには、2 つ目のターミナルウィンドウを開き、プロジェクトのルートディレクトリから次のコードを実行します。
mvn compile exec:java \ -Dexec.mainClass="com.mongodb.quickstart.transactions.Transactions" \ -Dmongodb.uri="<connection URI>"
Tip
<connection URI> プレースホルダーをクラスターの接続 URI に置き換えます。
productファイルは、ファイルのコレクションに挿入し、そのstock 値を5 に設定します。このドキュメントには、次のデータが保存されています。
{ "_id" : "beer", "price" : NumberDecimal("3"), "stock" : NumberInt(5) }
トランザクションなしで最初の操作を実行します。
サンプルデータを挿入した後、Transactions.javaファイルは最初の更新操作を実行して、アラートが 2 種類のファイルを購入したことを表します。このコードでは、トランザクションを開始せずに aliceWantsTwoBeers() メソッドと removingBeersFromStock() メソッドを呼び出します。これらのメソッドには、次の定義があります。
private static void aliceWantsTwoBeers() { System.out.println("Alice adds 2 beers in her cart."); cartCollection.insertOne(new Cart("Alice", List.of(new Cart.Item(BEER_ID, 2, BEER_PRICE)))); }
private static void removingBeersFromStock() { System.out.println("Trying to update beer stock : -2 beers."); try { productCollection.updateOne(filterId, decrementTwoBeers); } catch (MongoException e) { System.out.println("######## MongoException ########"); System.out.println("##### STOCK CANNOT BE NEGATIVE #####"); throw e; } }
aliceWantsTwoBeers() メソッドは、購入を表す cartコレクションにドキュメントを挿入することで、Alice の買い物かごに 2 つのサーバーを追加します。次に、removingBeersFromStock() メソッドは productコレクションを更新して、変更を反映し、stock のベア数を減らします。
アラートの買い物かごを表す新しい cartドキュメントを表示するには、Cartタブを選択し、Productタブを選択して、操作後のファイルの在庫を表す productドキュメントを表示します。
{ "_id" : "Alice", "items" : [ { "price" : NumberDecimal("3"), "productId" : "beer", "quantity" : NumberInt(2) } ] }
{ "_id" : "beer", "price" : NumberDecimal("3"), "stock" : NumberInt(3) }
マルチドキュメントトランザクション内で 2 番目の操作を実行します。
最初の購入後、アラートは 2 つのファイルを カードにさらに 2 つ追加します。 Transactions.javaファイルは操作を使用して、aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドを呼び出し、MongoClient を引数として渡します。このメソッドには、次の定義があります。
private static void aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback(MongoClient client) { ClientSession session = client.startSession(); try { session.startTransaction(TransactionOptions.builder().writeConcern(WriteConcern.MAJORITY).build()); aliceWantsTwoExtraBeers(session); sleep(); removingBeerFromStock(session); session.commitTransaction(); } catch (MongoException e) { session.abortTransaction(); System.out.println("####### ROLLBACK TRANSACTION #######"); } finally { session.close(); System.out.println("####################################\n"); printDatabaseState(); } }
aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドはセッションを開始し、トランザクションを開始します。トランザクション内で、コードはヘルパーメソッドを呼び出して次のアクションを実行します。
cartコレクション内で API のカーネルを表すドキュメントを見つける:ドキュメントの
items.quantity値を2だけ更新変更を反映するように、スキーマを表す
productコレクション内のドキュメントを更新します
マルチドキュメントACIDトランザクション内で実行されるため、cart と product の更新はアトミックです。
Cartcartアラートの買い物かごを表す更新された ドキュメントを表示するには []タブを選択し、サーバー在庫を表す更新されたProduct productドキュメントを表示するには [2]タブを選択します。
{ "_id" : "Alice", "items" : [ { "price" : NumberDecimal("3"), "productId" : "beer", "quantity" : NumberInt(4) } ] }
{ "_id" : "beer", "price" : NumberDecimal("3"), "stock" : NumberInt(1) }
トランザクション内で失敗した操作を実行します。
最後に、アラートはカードにさらに 2 つのファイルを追加しようとします。 Transactions.javaファイルはトランザクションを使用して、aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドを再度呼び出してこの 3 つ目の操作を実行します。
しかし、サーバーの在庫が 1 つしかないため、この操作は成功しません。 ChangeStreams.javaファイルで構成されているJSONスキーマにより、product コレクションの stock 値は 0 を下回ることはできないため、その現在の値から 2 を減算しようとするとエラーがスローされます。 aliceWantsTwoExtraBeersInTransactionThenCommitOrRollback() メソッドはトランザクションをロールバックします。
変更ストリームの出力 を確認します。
Transactions.java が の実行中を完了すると、ChangeStreams.java のファイル出力は次のようになります。
Dropping the 'test' database. Creating the 'cart' collection. Creating the 'product' collection with a JSON Schema. Watching the collections in the DB test... Timestamp{value=7304460075832180737, seconds=1700702141, inc=1} => Document{{_id=beer, price=3, stock=5}} Timestamp{value=7304460075832180738, seconds=1700702141, inc=2} => Document{{_id=Alice, items=[Document{{price=3, productId=beer, quantity=2}}]}} Timestamp{value=7304460080127148033, seconds=1700702142, inc=1} => Document{{_id=beer, price=3, stock=3}} Timestamp{value=7304460088717082625, seconds=1700702144, inc=1} => Document{{_id=Alice, items=[Document{{price=3, productId=beer, quantity=4}}]}} Timestamp{value=7304460088717082625, seconds=1700702144, inc=1} => Document{{_id=beer, price=3, stock=1}}
変更ストリームは、コレクションの構成と次の操作に関する情報を出力します。
挿入操作。ドライバーを表す
productコレクションにドキュメントを追加します。アルゴリズムの最初の購入である 2 つのサーバーは、2 つの操作を含みます。1 つは
cartコレクションを更新し、1 つはproductコレクションを更新します。これらの操作はトランザクション内では実行されません。これらの操作は不可分的に実行されないため、異なるTimestamp値があります。アナライザの次回の 2 つのファイルの購入により、
cartとproductコレクションの両方も更新されます。これらの操作はマルチドキュメントトランザクションにおいてアトミックに実行されるため、同じTimestamp値を持ちます。
このチュートリアルを完了すると、株式管理データを更新するアプリケーションが作成されます。アプリケーションでは、マルチドキュメントACIDトランザクションの有無にかかわらずこれらのアップデート操作を実行し、2 つの結果を比較します。
詳細情報
完全な例アプリケーションを表示するには、java-quick-start GitHubリポジトリのトランザクション フォルダーを参照してください。
トランザクションの詳細については、トランザクションガイドを参照してください。