This topic describes how to use conditional updates in the Tablestore SDK for Java. When you set update conditions, a target row is updated only if the specified conditions are met.
Prerequisites
Description
The Condition class is declared as follows:
public class Condition {
private RowExistenceExpectation rowExistenceExpectation;
private ColumnCondition columnCondition;
// Method declaration
}Sample code
The following code example shows how to perform a conditional update using the updateRow method.
public static void setConditionExample(SyncClient client) {
// Construct the update data.
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"));
PrimaryKey primaryKey = primaryKeyBuilder.build();
RowUpdateChange rowUpdateChange = new RowUpdateChange("test_condition", primaryKey);
rowUpdateChange.put("col1", ColumnValue.fromString("changed_val1"));
// Construct the update condition.
Condition condition = new Condition();
// Update the data only if the target row exists in the data table.
condition.setRowExistenceExpectation(RowExistenceExpectation.EXPECT_EXIST);
rowUpdateChange.setCondition(condition);
// Construct a request and call the updateRow method to update the data.
UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowUpdateChange);
UpdateRowResponse updateRowResponse = client.updateRow(updateRowRequest);
// Process the response.
System.out.println("* RequestId: " + updateRowResponse.getRequestId());
System.out.println("* Read CU Cost: " + updateRowResponse.getConsumedCapacity().getCapacityUnit().getReadCapacityUnit());
System.out.println("* Write CU Cost: " + updateRowResponse.getConsumedCapacity().getCapacityUnit().getWriteCapacityUnit());
}Set a column value condition to check whether the value of a single attribute column meets a specified condition.
// Update the data only if the value of the col1 column is val1. SingleColumnValueCondition singleColumnValueCondition = new SingleColumnValueCondition("col1", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString("val1")); condition.setColumnCondition(singleColumnValueCondition);Set a column value condition to check multiple sub-conditions.
// Set composite condition 1. CompositeColumnValueCondition compositeColumnValueCondition1 = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.AND); // Add sub-conditions. SingleColumnValueCondition singleColumnValueCondition1 = new SingleColumnValueCondition("col1", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString("val1")); compositeColumnValueCondition1.addCondition(singleColumnValueCondition1); SingleColumnValueCondition singleColumnValueCondition2 = new SingleColumnValueCondition("col2", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString("val2")); compositeColumnValueCondition1.addCondition(singleColumnValueCondition2); // Set composite condition 2. CompositeColumnValueCondition compositeColumnValueCondition2 = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.OR); // Add sub-conditions. compositeColumnValueCondition2.addCondition(compositeColumnValueCondition1); SingleColumnValueCondition singleColumnValueCondition3 = new SingleColumnValueCondition("col3", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString("val3")); compositeColumnValueCondition2.addCondition(singleColumnValueCondition3); // Add the composite condition. The condition is (col1 = val1 and col2 = val2) or (col3 = val3). condition.setColumnCondition(compositeColumnValueCondition2);
Use case
The following code sample shows how to use the conditional update feature to simulate a compare-and-swap (CAS) operation for optimistic locking.
public static void OptimisticLocking(SyncClient client) {
// Construct the primary key.
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"));
PrimaryKey primaryKey = primaryKeyBuilder.build();
// Read the original value of the attribute column.
SingleRowQueryCriteria singleRowQueryCriteria = new SingleRowQueryCriteria("test_condition", primaryKey);
singleRowQueryCriteria.setMaxVersions(1);
GetRowRequest getRowRequest = new GetRowRequest(singleRowQueryCriteria);
GetRowResponse getRowResponse = client.getRow(getRowRequest);
String oldValue = getRowResponse.getRow().getLatestColumn("col1").getValue().asString();
// Update the data.
RowUpdateChange rowUpdateChange = new RowUpdateChange("test_condition", primaryKey);
rowUpdateChange.put("col1", ColumnValue.fromString("changed_val1"));
// Set the update condition. The update is performed only if the latest version of the target attribute column equals the expected value (the read value).
Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
SingleColumnValueCondition singleColumnValueCondition = new SingleColumnValueCondition("col1", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString(oldValue));
singleColumnValueCondition.setPassIfMissing(false);
singleColumnValueCondition.setLatestVersionsOnly(true);
condition.setColumnCondition(singleColumnValueCondition);
rowUpdateChange.setCondition(condition);
// Construct a request and call the updateRow method to update the data.
UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowUpdateChange);
UpdateRowResponse updateRowResponse = client.updateRow(updateRowRequest);
// Process the response.
System.out.println("* RequestId: " + updateRowResponse.getRequestId());
System.out.println("* Read CU Cost: " + updateRowResponse.getConsumedCapacity().getCapacityUnit().getReadCapacityUnit());
System.out.println("* Write CU Cost: " + updateRowResponse.getConsumedCapacity().getCapacityUnit().getWriteCapacityUnit());
}