---
title: "OBKV-HBase 数据操作示例 - OceanBase 数据库 V4.3.5 | OceanBase 文档中心"
description: OBKV-HBase 数据操作示例 本文以具体的示例为例来介绍如果通过 OBKV-HBase 客户端进行数据处理。 说明 OBKV-HBase 客户端已支持的接口列表，参见 兼容 HBase 的接口 。 准备工作 基于以下示例进行体验之前，请确保您已经完成如下准备工作： 已经部署了 OceanBase 集群。关于支持…
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库KV 型 - V 4.3.5 LTS

# OBKV-HBase 数据操作示例

更新时间：2026-04-15 16:01:32

[编辑](https://github.com/oceanbase/oceanbase-kv/edit/V4.3.5/zh-CN/200.obkv-hbase/200.obkv-hbase-develop/300.obkv-hbase-demo.md)  

本文以具体的示例为例来介绍如果通过 OBKV-HBase 客户端进行数据处理。

#### 说明

OBKV-HBase 客户端已支持的接口列表，参见[兼容 HBase 的接口](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002022361)。

## 准备工作

基于以下示例进行体验之前，请确保您已经完成如下准备工作：

- 已经部署了 OceanBase 集群。关于支持的部署方案、部署方式以及详细的部署操作，参见 [部署简介](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001428865)。
 - 已经创建了 MySQL 租户。关于创建租户的详细操作，参见 [创建租户](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001428978)。
 - 已经创建了数据库。关于创建数据库的详细操作，参见 [创建数据库](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001431012)。
 - 已经创建了 OBKV-HBase 数据表。关于创建 OBKV-HBase 数据表的详细操作，参见 [数据库模式设计](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002022352)。

  在本示例中，表组名为 htable1。每个表对应一个列族，可按需建表。建表示例如下。

  ```
  CREATE TABLEGROUP htable1;

    CREATE TABLE htable1$family1 (
    `K` varbinary(1024) NOT NULL,
    `Q` varbinary(256) NOT NULL,
    `T` bigint(20) NOT NULL,
    `V` varbinary(1024) DEFAULT NULL,
    PRIMARY KEY (`K`, `Q`, `T`)
    )
    TABLEGROUP =  htable1
    PARTITION BY KEY(`K`) PARTITIONS 3;

    CREATE TABLE htable1$family2 (
    `K` varbinary(1024) NOT NULL,
    `Q` varbinary(256) NOT NULL,
    `T` bigint(20) NOT NULL,
    `V` varbinary(1024) DEFAULT NULL,
    PRIMARY KEY (`K`, `Q`, `T`)
    )
    TABLEGROUP =  htable1
    PARTITION BY KEY(`K`) PARTITIONS 3;

    CREATE TABLE htable1$family3 (
    `K` varbinary(1024) NOT NULL,
    `Q` varbinary(256) NOT NULL,
    `T` bigint(20) NOT NULL,
    `V` varbinary(1024) DEFAULT NULL,
    PRIMARY KEY (`K`, `Q`, `T`)
    )
    TABLEGROUP =  htable1
    PARTITION BY KEY(`K`) PARTITIONS 3;

  ```
 - 本示例通过 OHTable 连接 OBKV-HBase 集群并进行数据处理，请确保已经完成 OBKV-HBase 客户端的部署和配置，并通过 OHTable 连接了集群。详细操作参见 [使用 OBKV-HBase 客户端连接集群](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000002022354)。

## 注意事项

- 代码示例中的执行结果，依赖下面各个操作的顺序，如需复现，请按照顺序执行。
 - 为了比较直观的观察数据库中的结果，示例中采用 MySQL 客户端连接 OBKV-HBase，通过 SQL 来查询数据库表的状态。

#### 注意

OBKV-HBase 的 put、delete、get、scan 接口支持多列族。

## put

**函数说明：**

- put 操作允许一行中指定多列，支持多列族，多列族的写入可以保证原子性。
 - 未指定版本(时间戳)的情况下，本次写入列的版本是服务端执行时获取的时间戳，多个列族中写入列的版本一致。

**函数原型：**

- void put(Put put)
 - void put(List puts)

**参数列表：**

- put：put 对象，用于插入单条记录。
 - puts：put 对象集合，用于批量插入多条记录。

**操作示例：**

```java
Put put = new Put("testKey0".getBytes());
put.add("family1".getBytes(), "column1".getBytes(), "value1-1".getBytes());
put.add("family1".getBytes(), "column2".getBytes(), "value1-2".getBytes());
put.add("family2".getBytes(), "column3".getBytes(), "value2-3".getBytes());
put.add("family3".getBytes(), "column4".getBytes(), "value3-4".getBytes());
hTable.put(put);

```

```shell
MySQL [test]> SELECT * FROM htable1$family1;
+----------+---------+----------------+---------+
| K        | Q       | T              | V       |
+----------+---------+----------------+---------+
| testKey0 | column1 | -1730184389941 | value1-1|
| testKey0 | column2 | -1730184389941 | value1-2|
+----------+---------+----------------+---------+
2 rows in set

MySQL [test]> SELECT * FROM htable1$family2;
+----------+---------+----------------+---------+
| K        | Q       | T              | V       |
+----------+---------+----------------+---------+
| testKey0 | column3 | -1730184389941 | value2-3|
+----------+---------+----------------+---------+
1 row in set

MySQL [test]> SELECT * FROM htable1$family3;
+----------+---------+----------------+---------+
| K        | Q       | T              | V       |
+----------+---------+----------------+---------+
| testKey0 | column4 | -1730184389941 | value3-4|
+----------+---------+----------------+---------+
1 row in set

```

## get

**函数说明：**

- 获取指定行的数据。

**函数原型：**

- Result get(final Get get)
 - Result[] get(List gets)

**参数列表：**

- get：get 对象，需要使用 addColumn 或 addFamily 函数来指定操作目标。可以在单行 get 操作中任意组合并操作多个列族。返回值按 K 列 / Q 列字典序排序。

     - addColumn：
           - 用于指定要检索的特定列。
           - 需要提供列族和列限定符。
           - 适用于需要精确获取某个列的数据的场景。
           - 只会返回指定列的值。
     - addFamily：
           - 用于指定要检索的整个列族。
           - 只需要提供列族的名称。
           - 适用于需要获取整个列族中所有列的数据的场景。
           - 会返回该列族中所有列的值。
 - gets：get 对象列表，保存 get 对象。

**操作示例：**

```java
// 获取 family
int maxVersion = 1;
Get get = new Get("testKey0".getBytes());
get.addColumn("family1".getBytes(), "column1".getBytes());
get.addFamily("family2".getBytes());
Result result = hTable.get(get);
for (Cell cell : result.rawCells()) {
    System.out.println(new String(CellUtil.cloneRow(cell)) + " "
                        + new String(CellUtil.cloneFamily(cell)) + " "
                        + new String(CellUtil.cloneQualifier(cell)) + " "
                        + new String(CellUtil.cloneValue(cell)));
}

## 打印结果如下
## testKey0 family1 column1 value1-1
## testKey0 family2 column3 value2-3

```

```shell
## 上述 Get 操作转换为如下 SQL 查询
MySQL [test]> SELECT * FROM htable1$family1 WHERE k = "testKey0" AND Q = 'column1';
+----------+---------+----------------+---------+
| K        | Q       | T              | V       |
+----------+---------+----------------+---------+
| testKey0 | column1 | -1730184389941 | value1-1|
+----------+---------+----------------+---------+
1 row in set

MySQL [test]> SELECT * FROM htable1$family2 WHERE k = "testKey0";
+----------+---------+----------------+---------+
| K        | Q       | T              | V       |
+----------+---------+----------------+---------+
| testKey0 | column3 | -1730184389941 | value2-3|
+----------+---------+----------------+---------+
1 row in set

```

## scan

**函数说明：**

- 根据指定条件（scan/family/qualifier）对 Table 进行扫描。

**函数原型：**

- ResultScanner getScanner(byte[] family, byte[] qualifier)
 - ResultScanner getScanner(final byte[] family)
 - ResultScanner getScanner(final Scan scan)

**参数列表：**

- family：目标列簇，这里是指需要过滤的列簇。
 - qualifier：目标列名，这里指需要过滤的列名。
 - scan：Scan 对象，使用 addFamily 或 addColumn 等设置操作目标。
     - addColumn：
           - 用于指定要检索的特定列。
           - 需要提供列族和列限定符。
           - 适用于需要精确获取某个列的数据的场景。
           - 只会返回指定列的值。
     - addFamily：
           - 用于指定要检索的整个列族。
           - 只需要提供列族的名称。
           - 适用于需要获取整个列族中所有列的数据的场景。
           - 会返回该列族中所有列的值。

**操作示例：**

```java
Scan scan = new Scan("testKey0".getBytes());
scan.addColumn("family1".getBytes(), "column1".getBytes());
scan.addFamily("family2".getBytes());
scan.setStartRow("testKey0".getBytes());
ResultScanner scanner = hTable.getScanner(scan);

for (Result r : scanner) {
    for (Cell cell : r.rawCells()) {
        System.out.println(new String(CellUtil.cloneRow(cell)) + " "
                + new String(CellUtil.cloneFamily(cell)) + " "
                + new String(CellUtil.cloneQualifier(cell)) + " "
                + new String(CellUtil.cloneValue(cell)));
    }
}

```shell
## 上述 Scan 操作转换为如下 SQL 查询
MySQL [test]> SELECT *
    -> FROM htable1$family2
    -> WHERE K >= "testKey0"
    -> UNION  
    -> SELECT *
    -> FROM htable1$family1
    -> WHERE K >= "testKey0" AND Q = "column1";
+----------+---------+----------------+---------+
| K        | Q       | T              | V       |
+----------+---------+----------------+---------+
| testKey0 | column1 | -1730184389941 | value1-1|
| testKey0 | column3 | -1730184389941 | value2-3|
+----------+---------+----------------+---------+
2 rows in set

```

OBKV-HBase 支持 **Reverse Scan** 功能，它允许用户以行键（RowKey）逆序（从大到小）扫描表中的数据，这与常规的正序（从小到大）扫描相反。

正序扫描示例如下：

```shell
-- 正序扫描
String startKey = "testKey";
String endKey = "testKey9";
String family = "family";
String column = "column";
int maxVersion = 1;
Scan scan = new Scan();
scan.addColumn(family.getBytes(), column.getBytes());
scan.setMaxVersions(maxVersion);
scan.setStartRow(startKey.getBytes());
scan.setStopRow(endKey.getBytes());
ResultScanner scanner = hTable.getScanner(scan);
for (Result r : scanner) {
    for (KeyValue kv : r.list()) {
        System.out.printf("Scan Demo: Rowkey: %s, Column Family: %s, Column Qualifier: %s, Value: %s, Timestamp: %d%n",
                Bytes.toString(r.getRow()),
                Bytes.toString(kv.getFamily()),
                Bytes.toString(kv.getQualifier()),
                Bytes.toString(kv.getValue()),
                kv.getTimestamp());
    }
}

```

返回结果如下：

```shell
+----------+--------+----------------+----------+
| K        | Q      | T              | V        |
+----------+--------+----------------+----------+
| testKey0 | column | -1715961561057 | putValue |
| testKey1 | column | -1715961561132 | putValue |
| testKey2 | column1 | -1715961561132 | putValue |
| testKey2 | column2 | -1715961561132 | putValue |
+----------+--------+----------------+----------+
4 rows in set

```

逆序扫描示例如下：

```shell
-- 逆序扫描
String startKey = "testKey9";
String endKey = "testKey";
String family = "family";
String column = "column";
int maxVersion = 1;
Scan scan = new Scan();
scan.addColumn(family.getBytes(), column.getBytes());
scan.setMaxVersions(maxVersion);
scan.setStartRow(startKey.getBytes());
scan.setStopRow(endKey.getBytes());
// 设置启用 Reverse scan
scan.setReversed(true);
ResultScanner scanner = hTable.getScanner(scan);
for (Result r : scanner) {
    for (KeyValue kv : r.list()) {
        System.out.printf("Scan Demo: Rowkey: %s, Column Family: %s, Column Qualifier: %s, Value: %s, Timestamp: %d%n",
                Bytes.toString(r.getRow()),
                Bytes.toString(kv.getFamily()),
                Bytes.toString(kv.getQualifier()),
                Bytes.toString(kv.getValue()),
                kv.getTimestamp());
    }
}

```

返回结果如下：

```shell
+----------+--------+----------------+----------+
| K        | Q      | T              | V        |
+----------+--------+----------------+----------+
| testKey2 | column1 | -1715961561132 | putValue |
| testKey2 | column2 | -1715961561132 | putValue |
| testKey1 | column | -1715961561132 | putValue |
| testKey0 | column | -1715961561057 | putValue |
+----------+--------+----------------+----------+
4 rows in set

```

## incrementColumnValue

**函数说明：**

- 对表中的某行单列数据进行自增，执行成功则返回自增后的值，指定列的 cell 必须是 long 类型（64 字节整型）。

**函数原型：**

- long incrementColumnValue(byte[] row, byte[] family, byte[] qualifier, long amount, boolean writeToWAL)

**参数列表：**

- row：行键。
 - family：目标列簇，这里是建表时指定的列簇。
 - qualifier：目标列名。
 - amount：增加的数量（可以为负值）。
 - writeToWAL：是否预写日志，OBKV-HBase 不需要设置。

**操作示例：**

```
// 这里展示的是对单列自增 1
String column = "incrementColumn";
String key = "incrementKey";
String family = "family";
long increment_value = 1L;
long ret = hTable.incrementColumnValue(
        key.getBytes(),
        family.getBytes(),
        column.getBytes(),
        increment_value);
System.out.printf("Increment Column Demo: ret: %b%n", ret);

```

```
MySQL [test]> select *,hex(v) from htable1$family where k = "incrementKey";
+--------------+-----------------+----------------+----------+------------------+
| K            | Q               | T              | V        | hex(v)           |
+--------------+-----------------+----------------+----------+------------------+
| incrementKey | incrementColumn | -1715961669857 |          | 0000000000000001 |
+--------------+-----------------+----------------+----------+------------------+

```

**备注：**

- 如果使用 MySQL 客户端查看 HBase 表，可能会发现对应 Cell 的 V 字段没有值，可以用 hex(v) 来显示。
 - 如上，Increment 的行为是如果数据库中查询不到满足条件的 Cell，那么会生成一个 Cell，值默认为 0，接着进行 Increment。

## increment

**函数说明：**

- 对指定行中的单列或多列进行增加，指定列的 cell 必须是 long 类型（64 字节整型）。

**函数原型：**

- Result increment(Increment increment)

**参数列表：**

- increment： Increment 类型，需要使用 addColumn 进行属性设置。

**操作示例：**

```
// 这里展示的是对单列自增 1
String column = "incrementColumn";
String key = "incrementKey";
String family = "family";
long increment_value = 1L;
Increment increment = new Increment(key.getBytes());
increment.addColumn(family.getBytes(), column.getBytes(), increment_value);
Result r = hTable.increment(increment);

for (KeyValue kv : r.list()) {
    System.out.printf("Increment Demo: Rowkey: %s, Value:%s%n",
            Bytes.toString(r.getRow()),
            Bytes.toLong(kv.getValue()));
}

```

```
MySQL [test]> select *,hex(v) from htable1$family where k = "incrementKey";
+--------------+-----------------+----------------+----------+------------------+
| K            | Q               | T              | V        | hex(v)           |
+--------------+-----------------+----------------+----------+------------------+
| incrementKey | incrementColumn | -1715961734681 |         | 0000000000000002 |
| incrementKey | incrementColumn | -1715961669857 |         | 0000000000000001 |
+--------------+-----------------+----------------+----------+------------------+

```

**备注：**

- 如上，对一个 Cell 多次做自增，会产生多个版本的 Cell。HBase 中没有 Update 的操作语义，对一个 Cell 的修改会变成多版本，用户可以指定版本来做查询。

## append

**函数说明：**

- 对指定行中的单列或多列进行增加（针对字符类型，例如 byte，string 等）。

**函数原型：**

- Result append(Append append)

**参数列表：**

- append：Append 类型，需要使用 add 函数进行属性设置。

**操作示例：**

```
String column = "appendColumn";
String key = "appendKey";
String family = "family";
Append append = new Append(key.getBytes());
append.add(family.getBytes(), column.getBytes(), toBytes("_append"));
Result r = hTable.append(append);
for (KeyValue kv : r.list()) {
    System.out.printf("Appand Demo: Rowkey: %s, Append Value:%s%n",
            Bytes.toString(r.getRow()),
            Bytes.toString(kv.getValue()));
}

```

```
MySQL [test]> select * from htable1$family where k = "appendKey";
+-----------+--------------+----------------+---------+
| K         | Q            | T              | V       |
+-----------+--------------+----------------+---------+
| appendKey | appendColumn | -1715961265748 | _append |
+-----------+--------------+----------------+---------+

```

**备注：**

- 如上，Append 的行为是如果数据库中查询不到满足条件的 Cell，那么会插入对应的 Cell，值默认为空串，接着对生成的记录进行 Append 操作。

## delete

**函数说明：**

- 删除指定的存储单元（cells）或行（rows）。

**函数原型：**

- void delete(Delete delete)
 - void delete(List deletes)

**参数列表：**

- delete：Delete 对象，这里是指需要执行删除的行，通过 deleteColumn、deleteColumns、deleteFamily 函数设置。可以在单行 Delete 操作中任意组合并操作多个列族。
     - deleteColumn：
           - 用于删除特定版本的单个列。
           - 需要指定列族、列限定符和时间戳。
           - 适用于需要删除某个特定版本的数据的场景。
     - deleteColumns：
           - 用于删除一个列的所有版本。
           - 只需要指定列族和列限定符。
           - 适用于需要删除某个列的所有历史数据的场景。
     - deleteFamily：
           - 用于删除指定列族中的所有列及其所有版本的数据。
           - 只需要指定列族的名称。
           - 适用于需要清空某个列族的所有数据的场景。

**操作示例：**

```java
// 删除 family1 所有的列和 family2 的 column3 列
// 此时再次 Get，只能查到 family1 和 family2 的 column3 列以外的值
Delete delete = new Delete(toBytes("testKey0"));
delete.deleteFamily("family1".getBytes());
delete.deleteColumns("family2".getBytes(), "column3".getBytes());
hTable.delete(delete);

```

```java
// 删除 testKey0 所有的列，此时再次 Get 无法查询到结果
Delete delete = new Delete(toBytes("testKey0"));
hTable.delete(delete);

```

## exists

**函数说明：**

- 判断在 Get 对象中设置的列簇或列是否存在，存在则返回 true，反之返回 false。

**函数原型：**

- boolean exists(Get get)

**参数列表：**

- get：Get 对象，使用 addFamily 或 addColumn 来设置操作目标。

**操作示例：**

```
String key = "testKey2";
String family = "family";
Get get = new Get(key.getBytes());
get.addFamily(family.getBytes());
boolean ret = hTable.exists(get);
System.out.printf("Exist Demo: ret: %b%n", ret);

```

```
MySQL [test]> select * from htable1$family where k = "testKey2";
+----------+--------+----------------+----------+
| K        | Q      | T              | V        |
+----------+--------+----------------+----------+
| testKey2 | column | -1715961561132 | putValue |
+----------+--------+----------------+----------+

```

**备注：**

- Exist 语义等同于 Get。

## checkAndPut

**函数说明：**

- 检查并替换指定列数据，如果条件满足并替换成功，返回 true，反之返回 false。

**函数原型：**

- boolean checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value, Put put)

**参数列表：**

- row：目标行键。
 - family：目标列簇。
 - qualifier：目标列名。
 - value：目标列值。
 - put：需要替换的列值。

**操作示例：**

```
String key = "testKey2";
String family = "family";
String column = "column";
String value = "putValue";
String new_value = "value_new";
Put put = new Put(key.getBytes());
put.add(family.getBytes(), column.getBytes(), new_value.getBytes());
boolean ret = hTable.checkAndPut(
        key.getBytes(),
        family.getBytes(),
        column.getBytes(),
        value.getBytes(),
        put);
System.out.printf("CheckAndPut Demo: ret: %b%n", ret);

```

```
MySQL [test]> select * from htable1$family where k = "testKey2";
+----------+--------+----------------+-----------+
| K        | Q      | T              | V         |
+----------+--------+----------------+-----------+
| testKey2 | column | -1715961408587 | value_new |
| testKey2 | column | -1715961035471 | putValue  |
+----------+--------+----------------+-----------+

```

**备注：**

- 将满足条件的，主键为 testKey2，值为 putValue 的Cell，做了修改，生成一个值为 value_new 的新版本的 Cell。

## checkAndDelete

**函数说明：**

- 匹配删除列，若匹配条件符合并删除成功，返回 true，反之返回 false。

**函数原型：**

- boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete)

**参数列表：**

- row：目标匹配行键。
 - family：目标列簇，这里是建表时指定的列簇。
 - qualifier：目标匹配列名。
 - value：目标匹配列值。
 - delete：预期需要删除的列。

**操作示例：**

```
String key = "testKey2";
String family = "family";
String column = "column";
String value = "value_new";
Delete delete = new Delete(key.getBytes());
delete.deleteColumn(family.getBytes(), column.getBytes());
boolean ret = hTable.checkAndDelete(
        key.getBytes(),
        family.getBytes(),
        column.getBytes(),
        value.getBytes(),
        delete);
System.out.printf("CheckAndDelete Demo: ret: %b%n", ret);

```

```
MySQL [test]> select * from htable1$family where k = "testKey2";
+----------+--------+----------------+----------+
| K        | Q      | T              | V        |
+----------+--------+----------------+----------+
| testKey2 | column | -1715961035471 | putValue |
+----------+--------+----------------+----------+

```

**备注：**

- 将满足条件的，主键为 testKey2，值为 value_new 的 Cell，做了删除，数据库中不存在这个 Cell。

## getConfiguration

**函数说明：**

- 返回操作实例中的 config 句柄，可用于在操作中变更属性。

**函数原型：**

- Configuration getConfiguration()

**参数列表：**

- 无

**操作示例：**

```
hTable.getConfiguration().set("rpc.execute.timeout", "1500");

```

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
