Special behavior inside transactions
Inside transactions, MongoDB server has a slightly different behavior.
Connection Settings
The MongoDB drivers offer a dedicated replica set name configuration option turing the driver into auto detection mode. This option helps identifying replica set master nodes and command routing during a transaction.
Make sure to add replicaSet to the MongoDB URI. Please refer to connection string options for further details.
|
Collection Operations
MongoDB does not support collection operations, such as collection creation, within a transaction. This also affects the on the fly collection creation that happens on first usage. Therefore make sure to have all required structures in place.
Transient Errors
MongoDB can add special labels to errors raised during transactional execution. Those may indicate transient failures
that might vanish by merely retrying the operation.
We highly recommend Spring Retry for those purposes. Nevertheless
one may override MongoTransactionManager#doCommit(MongoTransactionObject)
to implement a Retry Commit Operation
behavior as outlined in the MongoDB reference manual.
Count
MongoDB count
operates upon collection statistics which may not reflect the actual situation within a transaction.
The server responds with error 50851 when issuing a count
command inside of a multi-document transaction.
Once MongoTemplate
detects an active transaction, all exposed count()
methods are converted and delegated to the
aggregation framework using $match
and $count
operators, preserving Query
settings, such as collation
.
Restrictions apply when using geo commands inside of the aggregation count helper. The following operators cannot be used and must be replaced with a different operator:
-
$where
→$expr
-
$near
→$geoWithin
with$center
-
$nearSphere
→$geoWithin
with$centerSphere
Queries using Criteria.near(…)
and Criteria.nearSphere(…)
must be rewritten to Criteria.within(…)
respective Criteria.withinSphere(…)
. Same applies for the near
query keyword in repository query methods that must be changed to within
. See also MongoDB JIRA ticket DRIVERS-518 for further reference.
The following snippet shows count
usage inside the session-bound closure:
session.startTransaction();
template.withSession(session)
.execute(action -> {
action.count(query(where("state").is("active")), Step.class)
...
The snippet above materializes in the following command:
db.collection.aggregate(
[
{ $match: { state: "active" } },
{ $count: "totalEntityCount" }
]
)
instead of:
db.collection.find( { state: "active" } ).count()