表格存儲Tablestore入門手冊系列主要介紹表格存儲的各個功能接口和适用場景,幫助客戶了解和使用表格存儲Tablestore。本文對表格存儲Tablestore的UpdateRow接口進行介紹,包括其參數、功能示例、使用場景等。
接口概述
UpdateRow接口是表格存儲Tablestore提供的基礎讀寫接口之一,用于對某一行進行更新操作,若指定行不存在,UpdateRow也可以用于新增一行。這裡的更新包括新增、修改或删除某一列,如果使用了多版本功能,也可以對某列中指定的版本進行新增、修改或删除。此外,在接口參數中也可以指定條件,僅當滿足條件時進行更新。下面詳細介紹該接口的參數和功能。
接口參數說明
API定義和參數說明
首先是UpdateRow接口的API定義:
message UpdateRowRequest {
required string table_name = 1;
required bytes row_change = 2;
required Condition condition = 3;
optional ReturnContent return_content = 4;
}
message UpdateRowResponse {
required ConsumedCapacity consumed = 1;
optional bytes row = 2;
}
API定義中的具體參數說明,見官網API文檔:
https://help.aliyun.com/document_detail/27307.htmlSDK接口和參數說明
在項目代碼中對表格存儲Tablestore進行讀寫操作,是通過表格存儲Tablestore釋出的各語言SDK進行的,SDK對API進行了封裝,内部自動處理了請求的編碼和響應的解析等。是以對于表格存儲Tablestore的使用者來說,隻需要熟悉SDK的接口即可。
下面以Java SDK為例,介紹SDK中的UpdateRow接口和參數。
接口定義
同步接口(SyncClient):
/**
* 更新表中的一行資料。
* <p>若要更新的行不存在,則新寫入一行資料。</p>
* <p>更新操作可以包括新寫入一個屬性列或者删除一個屬性列的一個或多個版本。</p>
*
* @param updateRowRequest 執行UpdateRow操作所需的參數。
* @return TableStore服務傳回的結果
* @throws TableStoreException TableStore服務傳回的異常
* @throws ClientException 請求的傳回結果無效、或遇到網絡異常
*/
public UpdateRowResponse updateRow(UpdateRowRequest updateRowRequest)
throws TableStoreException, ClientException;
異步接口(AsyncClient):
/**
* 更新表中的一行資料。
* <p>若要更新的行不存在,則新寫入一行資料。</p>
* <p>更新操作可以包括新寫入一個屬性列或者删除一個屬性列的一個或多個版本。</p>
*
* @param updateRowRequest 執行UpdateRow操作所需的參數。
* @param callback 請求完成後調用的回調函數,可以為null,則代表不需要執行回調函數
* @return 擷取結果的Future
* @throws TableStoreException TableStore服務傳回的異常
* @throws ClientException 請求的傳回結果無效、或遇到網絡異常
*/
public Future<UpdateRowResponse> updateRow(
UpdateRowRequest updateRowRequest, TableStoreCallback<UpdateRowRequest, UpdateRowResponse> callback);
具體參數說明:
變量類型 | 說明 | 備注 |
---|---|---|
UpdateRowRequest | UpdateRow接口的請求類型,具體内容見後續說明。 | |
UpdateRowResponse | UpdateRow接口的傳回結果,具體内容見後續說明。 | |
TableStoreCallback callback | UpdateRow接口的異步回調函數。 | 僅适用于異步接口。 |
Future | 異步接口的UpdateRow接口傳回結果。 | 異步接口調用後不等待請求結束,立即傳回future,通過future.get()可以擷取實際接口響應的結果。 |
UpdateRowRequest參數說明

TxnRequest(基類) | 抽象類,包含TransactionId成員變量,繼承該類的請求類型可用于局部事務中。 | TransactionId的使用可參考局部事務的文檔。 |
UpdateRow接口的請求類型,包含一個成員變量:RowUpdateChange。 繼承自TxnRequest,表示該請求可用于局部事務中。 | ||
RowUpdateChange | 本次更新的具體請求參數。 |
RowUpdateChange參數說明
類說明 | 成員變量或接口 | ||
---|---|---|---|
RowChange(基類) | RowUpdateChange的基類,提供了設定表名、主鍵、更新條件、傳回類型等通用參數。 | tableName | 指定本次更新要操作的表名。 |
primaryKey | 指定本次要更新的行的主鍵。 | ||
condition | 指定本次更新操作的條件,可選。 | ||
returnType | 枚舉類型,預設為RT_NONE,表示不傳回行的内容,此外還有兩種值: (1)RT_PK: 傳回主鍵,适用于使用主鍵自增列功能的場景,用于傳回系統生成的自增主鍵值。 (2)RT_AFTER_MODIFY: 傳回修改的列的資料,适用于使用了原子加功能的場景,用于傳回原子加之後,某一列的值。此時需要設定returnColumnNames。 | ||
returnColumnNames | 當returnType為RT_AFTER_MODIFY時,指定要傳回的被修改的列的列名(适用于原子加的場景)。 | ||
UpdateRow的具體請求參數,繼承自RowChange類。 | put(String columnName, ColumnValue value) | 新增或修改某一列的值。 (系統内部會為該列生成一個新的版本号,單版本模式下無須關心該版本号) | |
put(String columnName, ColumnValue value, long version) | 新增或修改某一列的某一個版本。 (适用于多版本模式,手動指定版本号寫入) | ||
put(Column column) | 功能同上述put接口,隻是參數使用Column類型進行了封裝。 | ||
put(List column) | 功能同上述put接口,隻是參數為多列。 | ||
deleteColumns(String columnName) | 删除某列,多版本模式下會删除該列全部版本。 | ||
deleteColumn(String columnName, long version) | 删除某列的指定版本,适用于多版本模式下對特定版本進行删除。 | ||
increment(Column column) | 對某列進行原子加操作,僅适用于整型類型。 | ||
Condition | 本次更新的條件。可以指定行存在性條件和列條件,列條件比如“某列的值大于5”。 | rowExistenceExpectation | 行存在性條件,枚舉類型,有以下三種值: (1) IGNORE:不對行存在性進行判斷,預設即為IGNORE。 (2) EXPECT_EXIST: 期望該行存在,若不存在,請求會報錯。 (3) EXPECT_NOT_EXIST:期望該行不存在,若存在,請求會報錯。 注意: 通常情況下,若沒有特殊的設定條件的需求,使用IGNORE即可(保持預設,可不做設定),此時寫入性能也更好。 |
columnCondition | 列條件,可以設定單列條件(SingleColumnValueCondition),也可以設定多列組合條件(CompositeColumnValueCondition),具體見條件更新的文檔。 |
UpdateRowResponse參數說明
Response(基類) | requestId | 本次請求服務端傳回的requestId,用于問題調查,建議在出錯時列印到業務日志中。 |
traceId | 本次請求SDK生成的traceId,用于問題調查,建議在出錯時列印到業務日志中。 | |
consumedCapacity | 本次請求消耗的讀寫CU,用于計費。 | |
row | 預設情況下為null,僅當請求中returnType設定為傳回PK(RT_PK)或者某列修改後的值(RT_AFTER_MODIFY)時,傳回對應的内容。 |
功能示例
所有示例代碼可以在Tablestore-Examples項目中檢視。
Github位址:
https://github.com/aliyun/tablestore-examples/tree/master/basic/Java/DataManage/src/main/java/com/aliyun/tablestore/basic/dataManage基本更新操作
UpdateRow接口最常用的場景,是對某一行寫入一些列,或者删除一些列。通常,業務使用單版本表比較多,此時可以忽略列上多版本的概念,按照每列隻有一個值來了解。此時UpdateRow就是用于新增、修改或删除某些列。
新增:若寫入的屬性列之前不存在,UpdateRow執行後會新增該列。
修改:若寫入的屬性列之前已經有值,UpdateRow執行後會修改該列的值。
删除:UpdateRow可以用于删除某些列,若該列之前就不存在,則無影響,不會報錯。
示例代碼
下面的代碼執行一次UpdateRow操作,對某一行新增兩列,删除一列。
public void updateRowNormally() {
PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
.addPrimaryKeyColumn(PK1, PrimaryKeyValue.fromLong(1L))
.addPrimaryKeyColumn(PK2, PrimaryKeyValue.fromString("string"))
.build();
/**
* 構造RowUpdateChange,設定表名和主鍵
*/
RowUpdateChange rowChange = new RowUpdateChange(TABLE_NAME, primaryKey);
/**
* 寫入兩列
*/
rowChange.put("col_str", ColumnValue.fromString("value1"));
rowChange.put("col_long", ColumnValue.fromLong(1));
/**
* 删除某列
*/
rowChange.deleteColumns("col_to_delete");
/**
* 構造UpdateRowRequest
*/
UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowChange);
/**
* 調用updateRow接口。若之前該行不存在,系統會新增該行。
*/
UpdateRowResponse updateRowResponse = syncClient.updateRow(updateRowRequest);
/**
* 列印requestID
*/
System.out.printf("UpdateRowSuccess, request id: %s\n", updateRowResponse.getRequestId());
}
使用UpdateRow新增、修改或者删除某些列,是最基礎的單行資料更新操作,也是很常用的場景。
但在某些場景中,若使用了表格存儲Tablestore的多版本功能,可能會有新增或修改某一列的某個特定版本的需求,或者是需要删除某一列的某一個版本,此時就需要指定時間戳來更新或删除,見下面的示例。
指定版本操作
對于設定了保留多版本的表,每一列上都會保留最新的N個版本,UpdateRow可以對其中某個特定版本進行更新,也可以删除某個特定版本。
下面的代碼執行一次UpdateRow操作,對某一行寫入兩列,指定版本号寫入,同時删除某列的某個版本,也需要指定要删除的版本号。
注意:在指定版本号時,需要保證該版本号在表上設定的最大版本偏差内,若超出該偏差範圍,可以調整表上的最大版本偏差設定(見文檔:
https://help.aliyun.com/document_detail/89939.html)。
public void updateRowMultiVersion() {
PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
.addPrimaryKeyColumn(PK1, PrimaryKeyValue.fromLong(1L))
.addPrimaryKeyColumn(PK2, PrimaryKeyValue.fromString("string"))
.build();
/**
* 構造RowUpdateChange,設定表名和主鍵
*/
RowUpdateChange rowChange = new RowUpdateChange(TABLE_NAME, primaryKey);
long version = System.currentTimeMillis();
/**
* 寫入兩列,指定版本号。
* 若指定的版本之前不存在,則會新增一個版本;若該版本已存在,會修改該版本的值。
*/
rowChange.put("col_str", ColumnValue.fromString("value1"), version);
rowChange.put("col_long", ColumnValue.fromLong(1), version);
/**
* 删除某列的某一個版本,指定版本号。
*/
rowChange.deleteColumn("col_to_delete", version);
/**
* 構造UpdateRowRequest
*/
UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowChange);
/**
* 調用updateRow接口。若之前該行不存在,系統會新增該行。
*/
UpdateRowResponse updateRowResponse = syncClient.updateRow(updateRowRequest);
/**
* 列印requestID
*/
System.out.printf("UpdateRowSuccess, request id: %s\n", updateRowResponse.getRequestId());
}
條件更新
UpdateRow接口可以設定更新條件,僅當滿足條件時才進行更新,條件包括行存在性條件和列條件。
行存在性條件:在更新前檢查該行存在或不存在,僅當符合期望時才進行更新操作,否則抛錯。
列條件:目前支援 SingleColumnValueCondition 和 CompositeColumnValueCondition,是基于某一列或者某些列的列值進行條件判斷,比如“col_long的值應該大于5”等。基于列條件,可以使用表格存儲Tablestore實作分布式的樂觀鎖機制。
條件更新的功能文檔:
https://help.aliyun.com/document_detail/35194.html設定行存在性條件和列條件:
public void updateRowWithCondition() {
PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
.addPrimaryKeyColumn(PK1, PrimaryKeyValue.fromLong(1L))
.addPrimaryKeyColumn(PK2, PrimaryKeyValue.fromString("string"))
.build();
/**
* 構造RowUpdateChange,設定表名和主鍵
*/
RowUpdateChange rowChange = new RowUpdateChange(TABLE_NAME, primaryKey);
/**
* 設定行存在條件為期望行存在
*/
Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
/**
* 設定列條件,若隻需要檢查行存在性,可以不設定列條件。
*
* 這裡設定列條件為兩列的組合條件: "(col_boolean == true) && (col_long > 0)"
*/
CompositeColumnValueCondition colCondition = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.AND);
SingleColumnValueCondition subColCondition1 = new SingleColumnValueCondition(
"col_boolean",
SingleColumnValueCondition.CompareOperator.EQUAL,
ColumnValue.fromBoolean(true));
subColCondition1.setPassIfMissing(true); // setPassIfMissing(true),表示若該列不存在,也視為滿足條件。
SingleColumnValueCondition subColCondition2 = new SingleColumnValueCondition(
"col_long",
SingleColumnValueCondition.CompareOperator.GREATER_THAN,
ColumnValue.fromLong(0L));
colCondition.addCondition(subColCondition1).addCondition(subColCondition2);
subColCondition2.setPassIfMissing(false); // setPassIfMissing(false),表示若該列不存在,視為不滿足條件。
condition.setColumnCondition(colCondition);
rowChange.setCondition(condition);
/**
* 滿足條件時,寫入兩列
*/
rowChange.put("col_str", ColumnValue.fromString("value1"));
rowChange.put("col_long", ColumnValue.fromLong(1));
/**
* 構造UpdateRowRequest
*/
UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowChange);
/**
* 調用updateRow接口。
* 若不滿足設定的條件,比如該行不存在,或者不滿足列條件,會抛OTSException,ErrorCode為"OTSConditionCheckFail".
*/
UpdateRowResponse updateRowResponse = syncClient.updateRow(updateRowRequest);
/**
* 列印requestID
*/
System.out.printf("UpdateRowSuccess, request id: %s\n", updateRowResponse.getRequestId());
}
原子計數器
UpdateRow支援對某一整型列進行原子加操作,原子加操作可以原子的對某一整型列的資料進行增量變更操作,比如在原來的基礎上加10,或者減5,等等。原子加操作可以用來構造原子計數器。
原子計數器的功能文檔:
https://help.aliyun.com/document_detail/90949.htmlpublic void updateRowIncrement() {
PrimaryKey primaryKey = PrimaryKeyBuilder.createPrimaryKeyBuilder()
.addPrimaryKeyColumn(PK1, PrimaryKeyValue.fromLong(1L))
.addPrimaryKeyColumn(PK2, PrimaryKeyValue.fromString("string"))
.build();
/**
* 構造RowUpdateChange,設定表名和主鍵
*/
RowUpdateChange rowChange = new RowUpdateChange(TABLE_NAME, primaryKey);
String columnName = "col_long";
/**
* 對col_long這一列進行原子加100操作。
* 若該列之前不存在,會從0開始累加。
*/
rowChange.increment(new Column(columnName, ColumnValue.fromLong(100)));
/**
* 設定傳回修改後的該列值。
*/
rowChange.setReturnType(ReturnType.RT_AFTER_MODIFY);
rowChange.addReturnColumn(columnName);
/**
* 構造UpdateRowRequest
*/
UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowChange);
/**
* 調用updateRow接口。若之前該行不存在,系統會新增該行。
*/
UpdateRowResponse updateRowResponse = syncClient.updateRow(updateRowRequest);
/**
* 列印修改後的該列的值和RequestId
*/
System.out.printf("UpdateRowSuccess, column [%s] was updated to %d, request id: %s\n",
columnName,
updateRowResponse.getRow().getLatestColumn(columnName).getValue().asLong(),
updateRowResponse.getRequestId());
}
專家服務
如有疑問或者需要更好的線上支援,歡迎加入釘釘群:“表格存儲公開交流群”。群内提供免費的線上專家服務,歡迎掃碼加入,群号:23307953