Session: How to enable optimistic concurrency?
By default, optimistic concurrency checks are turned off, which means that changes made outside our session object will be overwritten.
Checks can be turned on by setting setUseOptimisticConcurrency
method from advanced
session operations to true
and may cause ConcurrencyExceptions
to be thrown.
Example I
try (IDocumentSession session = store.openSession()) {
session.advanced().setUseOptimisticConcurrency(true);
Product product = new Product();
product.setName("Some Name");
session.store(product, "products/999");
session.saveChanges();
try (IDocumentSession otherSession = store.openSession()) {
Product otherProduct = otherSession.load(Product.class, "products/999");
otherProduct.setName("Other name");
otherSession.saveChanges();
}
product.setName("Better Name");
session.saveChanges(); // throws ConcurrencyException
}
The above example shows how to enable optimistic concurrency for a particular session. However that can be also turned on globally, that is for all opened sessions
by using the convention setDefaultUseOptimisticConcurrency
.
Example II
store.getConventions().setDefaultUseOptimisticConcurrency(true);
try (IDocumentSession session = store.openSession()) {
boolean isSessionUsingOptimisticConcurrency = session.advanced().isUseOptimisticConcurrency(); // will return true
}
Remarks
Optimistic Concurrency and Replication
When Optimistic Concurrency is used with Replication then we advise to set forceReadFromMaster
when only read operations are load-balanced (FailoverBehavior.ReadFromAllServers) and you want to perform document update.
store.getConventions().setDefaultUseOptimisticConcurrency(true);
try (DocumentSession session = (DocumentSession) store.openSession()) {
try (CleanCloseable _ = session.getDatabaseCommands().forceReadFromMaster()) {
// In replicated setup where ONLY reads are load balanced (FailoverBehavior.ReadFromAllServers)
// and optimistic concurrency checks are turned on
// you must set 'ForceReadFromMaster' to get the appropriate ETag value for the document
// when you want to perform document updates (writes)
// because writes will go to the master server and ETag values between servers are not synchronized
Product product = session.load(Product.class, "products/999");
product.setName("New Name");
session.saveChanges();
}
}