条件更新

本文介绍如何在 Java SDK 中使用条件更新,设置更新条件后,只有目标行数据满足指定的条件,才能完成更新。

前提条件

初始化Tablestore Client

功能说明

条件更新的类声明如下:

public class Condition {
    private RowExistenceExpectation rowExistenceExpectation;
    private ColumnCondition columnCondition;
    
    // method declaration
}

属性说明

  • rowExistenceExpectation(可选):行存在性条件,包括以下三种。

    • IGNORE(默认值):不做行存在性判断。

    • EXPECT_EXIST:数据表中存在目标行数据时满足条件,否则不满足。

    • EXPECT_NOT_EXIST:数据表中不存在目标行数据时满足条件,否则不满足。

  • columnCondition(可选):列值判断条件,包括以下两种。

    • SingleColumnValueCondition:判断单个属性列的值是否满足条件。参数说明如下:

      名称

      类型

      说明

      operator(必选)

      CompareOperator

      关系运算符,包括 EQUAL(等于)、NOT_EQUAL(不等于)、GREATER_THAN(大于)、GREATER_EQUAL(大于等于)、LESS_THAN(小于)、LESS_EQUAL(小于等于)。

      columnName(必选)

      String

      判断的属性列名称。

      columnValue(必选)

      ColumnValue

      判断的值。

      passIfMissing(可选)

      boolean

      行数据不包含目标属性列时,是否满足条件,默认值为 true,即行数据不包含目标属性列时满足条件,否则不满足。

      latestVersionsOnly(可选)

      boolean

      是否只判断最新的数据版本,默认值为 true,即当目标属性列存在多个数据版本时,只判断最新的数据版本是否符合判断条件。

    • CompositeColumnValueCondition:判断行数据是否满足组合判断条件。参数说明如下:

      名称

      类型

      说明

      type(必选)

      LogicOperator

      逻辑运算符,包括 NOT(非)、AND(与)、OR(或)。

      conditions(必选)

      List<ColumnCondition>

      参与逻辑运算的子条件列表。

      • 子条件可以是 SingleColumnValueCondition 或 CompositeColumnValueCondition。

      • 最多支持 32 个条件的组合。

示例代码

以下示例代码以 updateRow 方法为例介绍如何设置条件更新。

public static void setConditionExample(SyncClient client) {
    // 构造更新数据
    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"));

    // 构造更新条件
    Condition condition = new Condition();
    // 目标行数据在数据表中存在时才进行数据更新
    condition.setRowExistenceExpectation(RowExistenceExpectation.EXPECT_EXIST);
    rowUpdateChange.setCondition(condition);

    // 构造 Request,调用 updateRow 方法更新数据
    UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowUpdateChange);
    UpdateRowResponse updateRowResponse = client.updateRow(updateRowRequest);

    // 返回结果处理
    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());
}
  • 设置列值判断条件,判断单个属性列的值是否满足条件。

    // col1 列的值等于 val1 时才进行数据更新
    SingleColumnValueCondition singleColumnValueCondition = new SingleColumnValueCondition("col1", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString("val1"));
    condition.setColumnCondition(singleColumnValueCondition);
  • 设置列值判断条件,对多个条件进行判断。

    // 设置组合条件 1
    CompositeColumnValueCondition compositeColumnValueCondition1 = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.AND);
    // 添加子条件
    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);
    // 设置组合条件 2
    CompositeColumnValueCondition compositeColumnValueCondition2 = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.OR);
    // 添加子条件
    compositeColumnValueCondition2.addCondition(compositeColumnValueCondition1);
    SingleColumnValueCondition singleColumnValueCondition3 = new SingleColumnValueCondition("col3", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromString("val3"));
    compositeColumnValueCondition2.addCondition(singleColumnValueCondition3);
    // 添加组合条件,判断条件为 (col1 = val1 and col2 = val2) or (col3 = val3)
    condition.setColumnCondition(compositeColumnValueCondition2);

场景案例

以下示例代码使用条件更新功能模拟乐观锁的 CAS 实现。

public static void OptimisticLocking(SyncClient client) {
    // 构造主键
    PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
    primaryKeyBuilder.addPrimaryKeyColumn("id", PrimaryKeyValue.fromString("row1"));
    PrimaryKey primaryKey = primaryKeyBuilder.build();

    // 读取原属性列的值
    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();

    // 更新数据
    RowUpdateChange rowUpdateChange = new RowUpdateChange("test_condition", primaryKey);
    rowUpdateChange.put("col1", ColumnValue.fromString("changed_val1"));
    // 设置更新条件,目标属性列最新版本的值等于预期值(读取到的值)时,才进行更新
    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);

    // 构造 Request,调用 updateRow 方法更新数据
    UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowUpdateChange);
    UpdateRowResponse updateRowResponse = client.updateRow(updateRowRequest);

    // 返回结果处理
    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());
}