Reputation: 1234
Currently, I am using the following code:-
(I have marked the two important lines in the code. Between these lines are just some operations on existing documents)
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;
}
////////
Now, I excepted that once I call abortTransaction()
, the collection would revert back to it's previous state as it was before //Important Line 1
. But that doesn't happend. As I keep making operations, they get saved in MonogDB and do not get reverted when // Important line 2
completes execution.
(Just in case, everything is in try catch
and there are no errors between any lines. The code successfully reaches the return
statement.)
Also, if required, I am using the following maven dependency:-
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.2.0</version>
</dependency>
How to do this operation properly such that everything gets done, or nothing gets done (i.e. rollback/abort).
Upvotes: 0
Views: 3833
Reputation: 1234
Correct answer was pretty simple...
(Found by referring to the link at the very bottom of @R2D2 's answer.)
(TL;DR :- Add clientSession
as the first parameter in updateOne
method).
All we had to do is this :-
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;
}
////////
Upvotes: 1
Reputation: 10707
You need to include the write operations inside the session transaction , example:
original state of collection:
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 Now you start session:
session = db.getMongo().startSession()
2 Now you start transaction in the started session:
mongos> session.startTransaction()
3 You insert test document to the collection in the transaction:
mongos> session.getDatabase("test").tra.insert({a:"this will be aborted",today : new Date()})
WriteResult({ "nInserted" : 1 })
4 Check the collection now , there is no inserted document(transaction is yet not commited):
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 Now abort the transaction:
mongos> session.abortTransaction()
6 As you can see nothing is inserted(transaction was aborted):
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>
Afcourse if you replace step 5 with session.commitTransaction() the transaction will be commited and you will see the operations applied to the collection.
There is nice java example here : https://www.mongodb.com/blog/post/java-and-mongodb-40-support-for-multidocument-acid-transactions
Upvotes: 2