MongoDB(80)如何在MongoDB中使用多文档事务?

在MongoDB中使用多文档事务可以确保多个操作要么全部成功,要么全部失败,从而确保数据的一致性。MongoDB的多文档事务类似于传统关系型数据库的事务,支持ACID(原子性、一致性、隔离性和持久性)特性。以下是详细的步骤和Java代码示例,展示如何在MongoDB中使用多文档事务。

前提条件

  1. 复制集:事务需要在MongoDB复制集(Replica Set)或分片集群(Sharded Cluster)中运行。
  2. MongoDB版本:确保使用MongoDB 4.0或更高版本。

1. 引入Maven依赖

首先,在 pom.xml 中引入 MongoDB Java 驱动依赖:

xml 复制代码
<dependency>
  <groupId>org.mongodb</groupId>
  <artifactId>mongodb-driver-sync</artifactId>
  <version>4.4.0</version>
</dependency>

2. Java代码示例

以下是一个完整的Java代码示例,展示如何在MongoDB中使用多文档事务:

java 复制代码
import com.mongodb.MongoClientSettings;
import com.mongodb.MongoException;
import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.TransactionOptions;
import com.mongodb.WriteConcern;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

public class MongoDBTransactionExample {

    public static void main(String[] args) {

        // 创建 MongoClient
        MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");

        // 获取数据库和集合
        MongoDatabase database = mongoClient.getDatabase("testdb");
        MongoCollection<Document> collection1 = database.getCollection("collection1");
        MongoCollection<Document> collection2 = database.getCollection("collection2");

        // 插入一些初始数据
        collection1.insertOne(new Document("account", "Alice").append("balance", 100));
        collection2.insertOne(new Document("account", "Bob").append("balance", 0));

        // 开始会话
        ClientSession session = mongoClient.startSession();

        // 配置事务选项
        TransactionOptions txnOptions = TransactionOptions.builder()
                .readPreference(ReadPreference.primary())
                .readConcern(ReadConcern.LOCAL)
                .writeConcern(WriteConcern.MAJORITY)
                .build();

        try {
            // 开始事务
            session.startTransaction(txnOptions);

            // 执行跨集合的写操作
            Document aliceAccount = collection1.find(session, new Document("account", "Alice")).first();
            if (aliceAccount != null && aliceAccount.getInteger("balance") >= 50) {
                collection1.updateOne(session, new Document("account", "Alice"),
                        new Document("$inc", new Document("balance", -50)));
                collection2.updateOne(session, new Document("account", "Bob"),
                        new Document("$inc", new Document("balance", 50)));
            } else {
                throw new RuntimeException("Insufficient balance!");
            }

            // 提交事务
            session.commitTransaction();
            System.out.println("Transaction committed.");
        } catch (MongoException | RuntimeException e) {
            // 回滚事务
            session.abortTransaction();
            System.err.println("Transaction aborted due to: " + e.getMessage());
        } finally {
            session.close();
        }

        mongoClient.close();
    }
}

解释代码

  1. 创建 MongoClient:连接到 MongoDB 实例。
java 复制代码
MongoClient mongoClient = MongoClients.create("mongodb://localhost:27017");
  1. 获取数据库和集合:获取所需的数据库和集合引用。
java 复制代码
MongoDatabase database = mongoClient.getDatabase("testdb");
MongoCollection<Document> collection1 = database.getCollection("collection1");
MongoCollection<Document> collection2 = database.getCollection("collection2");
  1. 插入初始数据:向集合中插入一些示例数据。
java 复制代码
collection1.insertOne(new Document("account", "Alice").append("balance", 100));
collection2.insertOne(new Document("account", "Bob").append("balance", 0));
  1. 开始会话 :通过 mongoClient.startSession() 开始一个会话。
java 复制代码
ClientSession session = mongoClient.startSession();
  1. 配置事务选项 :使用 TransactionOptions 配置事务的选项,比如读偏好、读关注和写关注。
java 复制代码
TransactionOptions txnOptions = TransactionOptions.builder()
        .readPreference(ReadPreference.primary())
        .readConcern(ReadConcern.LOCAL)
        .writeConcern(WriteConcern.MAJORITY)
        .build();
  1. 开始事务 :通过 session.startTransaction(txnOptions) 开始事务。
java 复制代码
session.startTransaction(txnOptions);
  1. 执行跨集合的写操作:在事务中执行多个集合的写操作。
java 复制代码
Document aliceAccount = collection1.find(session, new Document("account", "Alice")).first();
if (aliceAccount != null && aliceAccount.getInteger("balance") >= 50) {
    collection1.updateOne(session, new Document("account", "Alice"),
            new Document("$inc", new Document("balance", -50)));
    collection2.updateOne(session, new Document("account", "Bob"),
            new Document("$inc", new Document("balance", 50)));
} else {
    throw new RuntimeException("Insufficient balance!");
}
  1. 提交事务 :如果所有操作成功,通过 session.commitTransaction() 提交事务。
java 复制代码
session.commitTransaction();
System.out.println("Transaction committed.");
  1. 回滚事务 :如果发生异常,通过 session.abortTransaction() 回滚事务。
java 复制代码
catch (MongoException | RuntimeException e) {
    session.abortTransaction();
    System.err.println("Transaction aborted due to: " + e.getMessage());
}
  1. 关闭会话和客户端:最后关闭会话和 MongoDB 客户端连接。
java 复制代码
finally {
    session.close();
}

mongoClient.close();

总结

通过上述代码示例,展示了如何在MongoDB中使用多文档事务来实现ACID特性。合理利用这些特性,可以在复杂应用场景中确保数据的一致性和可靠性。通过事务,可以保证在多个集合中的操作具有原子性、一致性、隔离性和持久性,从而确保数据的可靠性和一致性。

相关推荐
Bioinfo Guy43 分钟前
高分Panel复现系列|转录因子网络太乱?用模块框把重点圈出来
数据库·生物信息学·生信可视化
leisoo80971 小时前
100GBA股股票数据怎么存ClickHouseRedisMySQLJSON完整对比
大数据·linux·服务器·开发语言·python
WangYan20221 小时前
基于XGBoost与AI的生态—地学多源数据建模:植被与土地利用识别、土壤碳氮空间预测、生物多样性驱动机制、土壤微生物功能预测、生态退化与风险识别
python·机器学习·xgboost
ltl2 小时前
Disaggregated DB 合集:Socrates、PolarDB、Taurus 的共同模式
数据库
金銀銅鐵3 小时前
[Python] 借助 turtle 逐字展示唐诗《金缕衣》
python
Blossom i4 小时前
大数据预处理与采集实验一:使用Python操作MySQL数据库
数据库·mysql
雾时之林5 小时前
Linux--软件管理、源码包安装
linux·服务器·数据库
Python大数据分析@5 小时前
使用大模型MCP采集数据,爬虫已经无门槛
python·网络爬虫
quantdash_cc6 小时前
告别自建 Requests/BS4 网页爬虫:基于 QuantDash 搭建零维保的高性能量化行情流水线
开发语言·爬虫·python·pandas·量化·quantdash
65岁退休Coder6 小时前
LangChain v1.3.4 笔记 - 07 补充:链式调用 LCEL
后端·python·langchain