All Products
Search
Document Center

Tablestore:Use conditional updates

Last Updated:Jun 25, 2026

Attach a condition to a write or delete operation in Tablestore SDK for Java. Tablestore performs the operation only when the target row meets the condition; otherwise, it returns an error. Use conditional update to implement optimistic locking or to avoid overwriting concurrent changes that you have not read.

Prerequisites

Install Tablestore SDK for Java and initialize a client.

How it works

Conditional update lets you attach a condition to a write or delete operation. The Condition container holds a row existence condition (rowExistenceExpectation), a column condition (columnCondition), or both. Pass the configured Condition to setCondition() on RowPutChange, RowUpdateChange, or RowDeleteChange. If the condition is not met, the server returns an error and the row remains unchanged.

The classes include:

public class Condition {
    private RowExistenceExpectation rowExistenceExpectation;
    private ColumnCondition columnCondition;
}

public class SingleColumnValueCondition extends ColumnCondition

public class CompositeColumnValueCondition extends ColumnCondition

The following example updates the row with primary key row1 in the condition_demo table only when the row exists. Otherwise, the server returns an error.

PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"))
        .build();

RowUpdateChange rowUpdateChange = new RowUpdateChange("condition_demo", primaryKey);
rowUpdateChange.put("col1", ColumnValue.fromString("changed_val1"));

Condition condition = new Condition();
condition.setRowExistenceExpectation(RowExistenceExpectation.EXPECT_EXIST);
rowUpdateChange.setCondition(condition);

UpdateRowResponse response = client.updateRow(new UpdateRowRequest(rowUpdateChange));
System.out.println("RequestId: " + response.getRequestId());
System.out.println("Write CU: " + response.getConsumedCapacity().getCapacityUnit().getWriteCapacityUnit());

See Parameters for the full field reference of Condition, rowExistenceExpectation, and columnCondition.

Parameters

Condition

Condition is the condition container. It includes a row existence condition field and a column condition field. At least one field must be set.

Name

Type

Description

rowExistenceExpectation (optional)

RowExistenceExpectation

The row existence condition. Valid values:

  • IGNORE (default): Skips the row existence check.

  • EXPECT_EXIST: Matches when the target row exists in the table.

  • EXPECT_NOT_EXIST: Matches when the target row does not exist in the table.

columnCondition (optional)

ColumnCondition

The column condition. The subclasses are SingleColumnValueCondition for single-column checks and CompositeColumnValueCondition for combined checks.

SingleColumnValueCondition

Construct with new SingleColumnValueCondition(columnName, operator, columnValue).

Name

Type

Description

columnName (required)

String

The name of the attribute column to check.

operator (required)

CompareOperator

The comparison operator. Valid values:

  • EQUAL

  • NOT_EQUAL

  • GREATER_THAN

  • GREATER_EQUAL

  • LESS_THAN

  • LESS_EQUAL

columnValue (required)

ColumnValue

The value to compare against.

passIfMissing (optional)

boolean

Whether to treat the row as meeting the condition when the target attribute column is missing. Default: true (missing column is treated as meeting the condition).

Set to false to treat a missing column as not meeting the condition.

latestVersionsOnly (optional)

boolean

Whether to check only the latest data version. Default: true.

Set to false to match when any version satisfies the condition.

CompositeColumnValueCondition

Construct with new CompositeColumnValueCondition(logicOperator). Add subconditions with addCondition(). You can add up to 32 subconditions.

Name

Type

Description

type (required)

LogicOperator

The logical operator. Valid values:

  • AND

  • OR

  • NOT

conditions (required)

List<ColumnCondition>

The subconditions for the logical operation. Add each subcondition with addCondition(). A subcondition is either a SingleColumnValueCondition or another CompositeColumnValueCondition — use the composite form to nest conditions.

Examples

Single column value condition

Use SingleColumnValueCondition to check a single attribute column value. The following example updates col2 for the row with primary key row1 only when col1 == "changed_val1".

PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"))
        .build();

RowUpdateChange rowUpdateChange = new RowUpdateChange("condition_demo", primaryKey);
rowUpdateChange.put("col2", ColumnValue.fromString("new_val2"));

Condition condition = new Condition();
SingleColumnValueCondition singleCondition = new SingleColumnValueCondition(
        "col1",
        SingleColumnValueCondition.CompareOperator.EQUAL,
        ColumnValue.fromString("changed_val1"));
condition.setColumnCondition(singleCondition);
rowUpdateChange.setCondition(condition);

client.updateRow(new UpdateRowRequest(rowUpdateChange));

Composite column value condition

Use CompositeColumnValueCondition to combine multiple conditions with logical operators. You can nest composite conditions inside one another. The following example builds the condition (col1 == "changed_val1" AND col2 == "new_val2") OR (col3 == "val3").

PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"))
        .build();

RowUpdateChange rowUpdateChange = new RowUpdateChange("condition_demo", primaryKey);
rowUpdateChange.put("col1", ColumnValue.fromString("final_val1"));

// Sub-condition: col1 == "changed_val1" AND col2 == "new_val2"
CompositeColumnValueCondition andCondition = new CompositeColumnValueCondition(
        CompositeColumnValueCondition.LogicOperator.AND);
andCondition.addCondition(new SingleColumnValueCondition(
        "col1",
        SingleColumnValueCondition.CompareOperator.EQUAL,
        ColumnValue.fromString("changed_val1")));
andCondition.addCondition(new SingleColumnValueCondition(
        "col2",
        SingleColumnValueCondition.CompareOperator.EQUAL,
        ColumnValue.fromString("new_val2")));

// Top-level OR: (col1 AND col2) OR (col3)
CompositeColumnValueCondition orCondition = new CompositeColumnValueCondition(
        CompositeColumnValueCondition.LogicOperator.OR);
orCondition.addCondition(andCondition);
orCondition.addCondition(new SingleColumnValueCondition(
        "col3",
        SingleColumnValueCondition.CompareOperator.EQUAL,
        ColumnValue.fromString("val3")));

Condition condition = new Condition();
condition.setColumnCondition(orCondition);
rowUpdateChange.setCondition(condition);

client.updateRow(new UpdateRowRequest(rowUpdateChange));

Optimistic locking with compare-and-swap

Implement compare-and-swap with conditional update: first read the current value, then pass it as the update condition. The update succeeds only when the column still holds the value you read. If another process modifies the column between your read and write, the update fails. This prevents you from overwriting that process's write.

PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
        .addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"))
        .build();

// 1. Read the current value.
SingleRowQueryCriteria queryCriteria = new SingleRowQueryCriteria("condition_demo", primaryKey);
queryCriteria.setMaxVersions(1);
GetRowResponse getResponse = client.getRow(new GetRowRequest(queryCriteria));
String oldValue = getResponse.getRow().getLatestColumn("col1").getValue().asString();

// 2. Perform a conditional update based on the value just read (only update if col1 still equals oldValue).
RowUpdateChange rowUpdateChange = new RowUpdateChange("condition_demo", primaryKey);
rowUpdateChange.put("col1", ColumnValue.fromString("cas_updated"));

Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
SingleColumnValueCondition casCondition = new SingleColumnValueCondition(
        "col1",
        SingleColumnValueCondition.CompareOperator.EQUAL,
        ColumnValue.fromString(oldValue));
casCondition.setPassIfMissing(false);
casCondition.setLatestVersionsOnly(true);
condition.setColumnCondition(casCondition);
rowUpdateChange.setCondition(condition);

client.updateRow(new UpdateRowRequest(rowUpdateChange));