[英]What is proper code pattern to finalize transactions in Java (rollback on exception and commit on success)?
[英]Commit and Rollback transactions in MongoDB Java
目前,我正在使用以下代码:-
(我在代码中标出了重要的两行,这两行之间只是对现有文档的一些操作)
clientSession.startTransaction(); // Important Line 1.
Document walletDetailDoc = new Document("identifier", "walletBalanceDistribution");
Document foundWalletDetailDoc1 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
walletDetailDoc = new Document("identifier", to + "Backup");
Document foundWalletDetailDoc2 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
walletDetailDoc = new Document("identifier", from + "Backup");
Document foundWalletDetailDoc3 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
assert foundWalletDetailDoc1 != null;
assert foundWalletDetailDoc2 != null;
assert foundWalletDetailDoc3 != null;
Bson updateWalletDoc = walletDetailDoc;
Bson updateWalletDocOperation = new Document("$set", updateWalletDoc);
walletDistributionCollection.updateOne(foundWalletDetailDoc1, updateWalletDocOperation);
updateWalletDoc = new Document("identifier", "walletBalanceDistribution")
.append("totalRTKBalanceForPool", foundWalletDetailDoc2.get("totalRTKBalanceForPool"))
.append("lastCheckedBlockNumber", foundWalletDetailDoc2.get("lastCheckedBlockNumber"))
.append("lastCheckedTransactionIndex", foundWalletDetailDoc2.get("lastCheckedTransactionIndex"))
.append("balanceCollectedAsFees", foundWalletDetailDoc2.get("balanceCollectedAsFees"));
updateWalletDocOperation = new Document("$set", updateWalletDoc);
//////// TEMPORARY... TO BE REMOVED
Thread.sleep(5000);
clientSession.abortTransaction(); // Important Line 2
boolean abc = true;
if(abc) {
return;
}
////////
现在,我例外的是,一旦我调用abortTransaction()
,该集合将恢复为之前的 state ,就像在//Important Line 1
之前一样。 但这并没有发生。 当我继续进行操作时,它们会保存在 MonogDB 中,并且不会在// Important line 2
完成执行时恢复。
(以防万一,一切都在try catch
并且任何行之间都没有错误。代码成功到达return
语句。)
此外,如果需要,我正在使用以下 maven 依赖项:-
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.2.0</version>
</dependency>
如何正确地执行此操作,以便一切都完成,或者什么都不做(即回滚/中止)。
您需要在 session 事务中包含写操作,例如:
原装 state 合集:
mongos> db.tra.find()
{ "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
{ "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
mongos>
1 现在开始 session:
session = db.getMongo().startSession()
2 现在您在启动的 session 中启动事务:
mongos> session.startTransaction()
3 您将测试文档插入到事务中的集合中:
mongos> session.getDatabase("test").tra.insert({a:"this will be aborted",today : new Date()})
WriteResult({ "nInserted" : 1 })
4 现在检查集合,没有插入的文档(事务尚未提交):
mongos> db.tra.find()
{ "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
{ "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
5 现在中止事务:
mongos> session.abortTransaction()
6 如您所见,没有插入任何内容(事务已中止):
mongos> db.tra.find()
{ "_id" : ObjectId("601088bac5b64c7d32c73a8a"), "today" : ISODate("2021-01-26T21:25:14.835Z") }
{ "_id" : ObjectId("60108901c5b64c7d32c73a8b"), "today" : ISODate("2021-01-26T21:26:25.264Z") }
mongos>
当然,如果您将步骤 5 替换为 session.commitTransaction() 事务将被提交,您将看到应用于集合的操作。
这里有很好的 java 示例: https://www.mongodb.com/blog/post/java-and-mongodb-40-support-for-transaction
正确答案很简单...
(通过参考@R2D2 答案最底部的链接找到。)
(TL;DR:- 添加clientSession
作为updateOne
方法中的第一个参数)。
我们所要做的就是:-
clientSession.startTransaction(); // Important Line 1.
Document walletDetailDoc = new Document("identifier", "walletBalanceDistribution");
Document foundWalletDetailDoc1 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
walletDetailDoc = new Document("identifier", to + "Backup");
Document foundWalletDetailDoc2 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
walletDetailDoc = new Document("identifier", from + "Backup");
Document foundWalletDetailDoc3 = (Document) walletDistributionCollection.find(walletDetailDoc).first();
assert foundWalletDetailDoc1 != null;
assert foundWalletDetailDoc2 != null;
assert foundWalletDetailDoc3 != null;
Bson updateWalletDoc = walletDetailDoc;
Bson updateWalletDocOperation = new Document("$set", updateWalletDoc);
walletDistributionCollection.updateOne(clientSession, foundWalletDetailDoc1, updateWalletDocOperation);
updateWalletDoc = new Document("identifier", "walletBalanceDistribution")
.append("totalRTKBalanceForPool", foundWalletDetailDoc2.get("totalRTKBalanceForPool"))
.append("lastCheckedBlockNumber", foundWalletDetailDoc2.get("lastCheckedBlockNumber"))
.append("lastCheckedTransactionIndex", foundWalletDetailDoc2.get("lastCheckedTransactionIndex"))
.append("balanceCollectedAsFees", foundWalletDetailDoc2.get("balanceCollectedAsFees"));
updateWalletDocOperation = new Document("$set", updateWalletDoc);
//////// TEMPORARY... TO BE REMOVED
Thread.sleep(5000);
clientSession.abortTransaction(); // Important Line 2
boolean abc = true;
if(abc) {
return;
}
////////
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.