HBase Java API 代码开发

1. API 介绍

几个主要 HBase API 类和数据模型之间的对应关系:

Java 类

HBase 数据模型

Admin

数据库(Database)

HBaseConfiguration

Table

表(Table)

HTableDescriptor

列簇(Column Family)

HColumnDescriptor

Put

列修饰符(Column Qualifier)

Get

Delete

Result

Scan

ResultScanner

 

1.1 Admin

关系:org.apache.hadoop.hbase.client.Admin

作用:提供了一个接口来管理 HBase 数据库的表信息。它提供的方法包括:创建表、删除表、列出表项,使表有效或无效,以及添加或删除表列簇成员等。

返回值

函数

描述

void

addColumn(TableName tableName, HColumnDescriptor column)

向一个已经存在的表添加列

checkHBaseAvaliable(HBaseConfiguration conf)

静态函数,查看 HBase 是否处于运行状态

createTable(HTableDescriptor desc)

创建一个表,同步操作

deleteTable(TableName tableName)

删除一个已经存在的表

enabelTable(TableName tableName)

使表处于有效状态

disableTable(TableName tableName)

使表处于无效状态(在删除一个表时候,要先使这个表处于无效状态)

HTableDescriptor[]

listTables()

列出所有用户控件表项

void

modifyTable(byte[] tableName, HTableDescriptor htd)

修改表的模式,是异步的操作,可能需要花费一定的时间

boolean

tableExists(String tableName)

检查表是否存在

 

1.2 HBaseConfiguration

关系:org.apache.hadoop.hbase.HBaseConfiguration

作用:对 HBase 进行配置

返回值

函数

描述

void

addResource(Path file)

通过给定的路径所指的文件来添加资源

void

clear()

清空所有已设置的属性

String

get(String name)

获取属性名对应的值

String

getBoolean(String name, boolean defaultValue)

获取为 boolean 类型的属性值,如果其属性值类型不为 boolean,则返回默认属性值

void

set(String name, String value)

通过属性名来设置值

void

setBoolean(String name, boolean value)

设置 boolean 类型的属性值

 

1.3 HTableDescriptor

关系:org.apache.hadoop.hbase.HTableDescriptor

作用:包含了表的名字及其对应表的列簇

返回值

函数

描述

void

addFamily(HColumnDescriptor family)

添加一个列簇

HColumnDescriptor

removeFamily(byte[] column)

移除一个列簇

byte[]

getName()

获取表的名字

byte[]

getValue(byte[] key)

获取属性的值

void

setValue(String key, String value)

设置属性的值

 

1.4 HColumnDescriptor

关系:org.apache.hadoop.hbase.HColumnDescriptor

作用:维护着关于列簇的信息,例如版本号,压缩设置等。它通常在创建表或者为表添加列簇的时候使用。列簇被创建后不能直接修改,只能通过删除然后重新创建的方式。列簇被删除的时候,列簇里面的数据也同时被删除。

返回值

函数

描述

byte[]

getName()

获取列簇的名字

byte[]

getValue(byte[] key)

获取对应的属性的值

void

setValue(String key, String value)

设置对应属性的值

 

1.5 Table

关系:org.apache.hadoop.hbase.client.Table

作用:可以用来和 HBase 表来直接通信,此方法对于更新操作来说是非线程安全的。

返回值

函数

描述

void

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

自动的检查 row, family, qualifier 是否与给定的值匹配

void

close()

释放所有的资源或挂起内部的缓冲区中的更新

boolean

exists(Get get)

检查 Get 实例所指定的值是否存在于 HTable 的列中

Result

get(Get get)

获取指定行的某些单元格所对应的值

byte[][]

getEndKeys()

获取当前打开的表每个区域的结束键值

ResultScanner

getScanner(byte[] family)

获取当前给定列簇的 Scanner 实例

HTableDescriptor

getTableDescriptor()

获取当前表的 HTableDescriptor 实例

byte[]

getTableName()

获取表名

static boolean

isTableEnabled(TableName tableName)

检查表是否有效

void

put(Put put)

向表中添加值

 

1.6 Put

关系:org.apache.hadoop.hbase.client.Put

作用:用来对单个行执行添加操作

返回值

函数

描述

Put

add(byte[] family, byte[] qualifier, byte[] value)

将指定的列和对应的值添加到 Put 实例中

Put

add(byte[] family, byte[] qualifier, long timeStamp, byte[] value)

将指定的列和对应的值及时间戳添加到 Put 实例中

byte[]

getRow()

获取 Put 实例的行

RowLock

getRowLock()

获取 Put 实例的行锁

long

getTimeStamp()

获取 Put 实例的时间戳

boolean

isEmpty()

检查 familyMap 是否为空

Put

setTimeStamp(long timeStamp)

设置 Put 实例的时间戳

用法示例:

Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName)); 
Put p = new Put(row); // 为指定行创建一个 Put 操作 
put.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(column), Bytes.toBytes(value));
table.put(p);

 

1.7 Get

关系:org.apache.hadoop.hbase.client.Get

作用:用来获取单个行的相关信息

返回值

函数

描述

Get

addColumn(byte[] family, byte[] qualifier)

获取指定列簇和列修饰符对应的列

Get

addFamily(byte[] family)

通过指定的列簇获取其对应列的所有列

Get

setTimeRange(long minStamp, long maxStamp)

获取指定范围的列的版本号

Get

setFilter(Filter filter)

当执行 Get 操作时设置服务器端的过滤器

用法示例:

Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName)); 
Get get = new Get(Bytes.toBytes(row));

 

1.8 Delete

关系:org.apache.hadoop.hbase.client.Delete

作用:用来封装一个要删除的信息

 

1.9 Scan

关系:org.apache.hadoop.hbase.client.Scan

作用:用来封装一个作为查询条件的信息

 

1.10 Result

关系:org.apache.hadoop.hbase.client.Result

作用:存储 Get 或 Scan 操作后获取表的单行值。使用此类提供的方法可以直接获取值或各种 Map 结构(Key-Value 对)

返回值

函数

描述

boolean

containsColumn(byte[] family, byte[] qualifier)

检查指定的列是否存在

NavigableMap

getFamilyMap(byte[] family)

获取对应列簇所包含的修饰符与值的键值对

byte[]

getValue(byte[] family, byte[] qualifier)

获取对应列的最新值

 

1.11 ResultScanner

关系:org.apache.hadoop.hbase.client.ResultScanner

作用:存储 Scan 操作后获取表的单行值

 

2. 基本增删改查的代码实现

Note: 切记,在将 string 类型转换为 byte[] 时,要使用 HBase 提供的工具类 Bytes.toBytes() 方法来转换。同样,在将 byte[] 转换为 string 类型时,要使用 Bytes.toString() 方法来进行转换操作。

package cn.gldwolf.hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.KeyValue.Type;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * @author: Gldwolf
 * @email: [email protected]
 * @date: 2019/6/20 10:41
 */

public class HBaseDemo {
    public static Configuration conf;
    private static final String ZK_CONNECT_STR = "hdp01:2181,hdp02:2181,hdp03:2181";

    static {
        conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum", ZK_CONNECT_STR);
    }

    /**
     * 创建表
     * @param tableName 表名
     * @param family 列簇列表
     * @throws IOException
     */
    public static void createTable(String tableName, String[] family) throws IOException {
        Admin admin = ConnectionFactory.createConnection(conf).getAdmin();
        TableName tbName = TableName.valueOf(tableName);  // 表的名称
        HTableDescriptor desc = new HTableDescriptor(tbName);  // 创建一个表的描述信息对象

        for (int i = 0; i < family.length; i++) {
            desc.addFamily(new HColumnDescriptor(family[i]));  // 将表的列簇信息添加到 HTableDescriptor 中
        }

        if (admin.tableExists(tbName)) {  // 判断表是否已经存在
            System.out.println(tbName.getNameAsString() + " is exists!");
            System.exit(0);
        } else {  // 如果不存在:创建一个表
            admin.createTable(desc);
            System.out.println("Congratulations, " + tbName.getNameAsString() + " created successfully!");
        }
    }

    /**
     * 往表中按照 rowKey 添加数据
     * @param rowKey
     * @param tableName 表名
     * @param column1 第一个列簇列表
     * @param value1 第一个列的值的列表
     * @param column2 第二个列簇
     * @param value2 第二个列的值的列表
     * @throws IOException
     */
    public static void addData(String rowKey, String tableName, String[] column1, String[] value1,
                               String[] column2, String[] value2) throws IOException {
        // 设置 rowKey
        Put put = new Put(Bytes.toBytes(rowKey));  // Put 用来对单个行执行添加操作

        // HTable 即 HBase 中的表,负责跟踪记录相关的操作:如增删改查等
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));

        // 获取所有的列簇
        HColumnDescriptor[] columnFamilies = table.getTableDescriptor().getColumnFamilies();

        for (int i = 0; i < columnFamilies.length; i++) {
            // 获取列簇名
            String familyName = columnFamilies[i].getNameAsString();

            // 往 article 列簇中 put 数据
            if (familyName.equals("article")) {
                for (int j = 0; j < column1.length; j++) {
                    put.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(column1[j]), Bytes.toBytes(value1[j]));
                }
            }

            // 往 author 列簇中添加数据
            if (familyName.equals("author")) {
                for (int j = 0; j < column2.length; j++) {
                    put.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(column2[j]), Bytes.toBytes(value2[j]));
                }
            }
        }
        table.put(put);
        System.out.println("Add data success!");
    }

    /**
     * 根据 rowKey 获取表中的数据
     * @param tableName 表名
     * @param rowKey
     * @return Result 一个 rowKey 对应的结果集合
     * @throws IOException
     */
    public static Result getResult(String tableName, String rowKey) throws IOException {
        Get get = new Get(Bytes.toBytes(rowKey));  // Get 是用来获取单行数据的对象

        // 获取表对象
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));

        // 获取结果集
        Result result = table.get(get);
        for (Cell cell : result.listCells()) {
            printCell(cell);
        }
        return result;
    }

    /**
     * 打印单个 cell 信息
     * @param cell 一个数据单元
     */
    public static void printCell(Cell cell) throws UnsupportedEncodingException {
        byte[] rowArray = cell.getRowArray();
        for (byte row : rowArray) {

        }
        System.out.println("RowKey: " + Bytes.toString(cell.getRowArray()));
        System.out.println("Family: " + Bytes.toString(cell.getFamilyArray()));
        System.out.println("Qualifier: " + Bytes.toString(cell.getQualifierArray()));
        System.out.println("Value: " + Bytes.toString(cell.getValueArray()));
        System.out.println("TimeStamp: " + cell.getTimestamp());
        System.out.println("-------------------------");
    }

    /**
     * 获取整个表的所有行数据,并打印所有的 Cell
     * @param tableName 表名
     * @throws IOException
     */

    public static void getResultScan(String tableName) throws IOException {
        Scan scan = new Scan();  // 在创建对象的时候要传入扫描的起始行和结束行,如果不给参数,那么就会 Scan 整个表

        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));

        // 获取 scan 后的结果对象
        ResultScanner rs = table.getScanner(scan);
        // 结果对象包含所有行的数据,而每个行中又有许多的 Cell
        for (Result r : rs) {
            for (Cell cell : r.listCells()) {
                printCell(cell);
            }
        }
        rs.close();
    }

    /**
     * 获取从 startRowKey 到 stopRowKey 的所有的行的数据,并打印包含的所有 Cell
     * @param tableName 表名
     * @param startRowKey 起始行
     * @param stopRowKey 结束行
     * @throws IOException
     */
    public static void getResultScan(String tableName, String startRowKey, String stopRowKey) throws IOException {
        Scan scan = new Scan(Bytes.toBytes(startRowKey), Bytes.toBytes(stopRowKey));  // 在创建对象的时候传入扫描的起始行和结束行

        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));

        // 获取 scan 后的结果对象
        ResultScanner rs = table.getScanner(scan);
        // 结果对象包含所有行的数据,而每个行中又有许多的 Cell
        for (Result r : rs) {
            for (Cell cell : r.listCells()) {
                printCell(cell);
            }
        }
        rs.close();
    }

    /**
     * 查询表的某一列的数据
     * @param tableName 表名
     * @param rowKey rowKey
     * @param familyName 列簇名
     * @param columName 列名
     * @throws IOException
     */
    public static void getResultByColumn(String tableName, String rowKey, String familyName, String columName) throws IOException {
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));
        Get get = new Get(Bytes.toBytes(rowKey));

        // 获取指定列簇和列修饰符对应的列
        get.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columName));
        Result results = table.get(get);
        for (Cell cell : results.listCells()) {
            printCell(cell);
        }
    }

    /**
     * 更新一个单元格中的数据
     * @param tableName 表名
     * @param rowKey
     * @param familyName 列簇名
     * @param columnName 列名
     * @param value 值
     * @throws IOException
     */
    public static void updateTable(String tableName, String rowKey, String familyName, String columnName, String value) throws IOException {
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));
        Put put = new Put(Bytes.toBytes(rowKey));

        // 创建一个 Cell,需要用 CellUtil 的 createCell 方法来创建
        Cell cell = CellUtil.createCell(Bytes.toBytes(rowKey),
                Bytes.toBytes(familyName), // 列簇名
                Bytes.toBytes(columnName), // 列名
                System.currentTimeMillis(), // 时间戳
                Type.Put.getCode(), // 类型
                Bytes.toBytes(value)); // 值

        // 住 Put 对象中添加 Cell
        put.add(cell);

        // 执行 update 操作
        table.put(put);
        System.out.println("Update table success!");
    }

    /**
     * 查询某列数据的多个版本
     * @param tableName 表名
     * @param rowKey
     * @param familyName 列簇名
     * @param columnName 列名
     * @throws IOException
     */
    public static void getResultByVersion(String tableName, String rowKey, String familyName, String columnName) throws IOException {
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName.getBytes()));
        Get get = new Get(Bytes.toBytes(rowKey));

        // 往 Get 对象中添加列簇信息和列信息
        get.addColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName));

        // 设置 version 为 5
        get.setMaxVersions(5);
        Result results = table.get(get);
        for (Cell cell : results.listCells()) {
            printCell(cell);
        }
    }

    /**
     * 删除一行中的一个指定的列
     * @param tableName 表名
     * @param rowKey
     * @param familyName 列簇名
     * @param columnName 列名
     * @throws IOException
     */
    public static void deleteOneColumnOfOneRow(String tableName, String rowKey, String familyName, String columnName) throws IOException {
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));

        // 创建一个行级的 Delete 对象
        Delete deleteColumn = new Delete(Bytes.toBytes(rowKey));

        // 指定要删除的列
        deleteColumn.addColumns(Bytes.toBytes(familyName), Bytes.toBytes(columnName));
        table.delete(deleteColumn);
        System.out.println(rowKey + ": " + familyName + ": " + columnName + "is deleted!");
    }

    /**
     * 删除一行的所有列
     * @param tableName 表名
     * @param rowKey
     * @throws IOException
     */
    public static void deleteAllColumnOfOneRow(String tableName, String rowKey) throws IOException {
        Table table = ConnectionFactory.createConnection(conf).getTable(TableName.valueOf(tableName));
        Delete deleteColumn = new Delete(Bytes.toBytes(rowKey)); // 此时就不用添加列簇名和列名了,因为要删除这一行中的所有数据
        table.delete(deleteColumn);
        System.out.println(rowKey + " all columns are deleted!");
    }

    /**
     * 删除一个表
     * @param tableName 表名
     * @throws IOException
     */
    public static void deleteTable(String tableName) throws IOException {
        Admin admin = ConnectionFactory.createConnection(conf).getAdmin();

        // 在删除表之前要先将表停
        admin.disableTable(TableName.valueOf(tableName));
        admin.deleteTable(TableName.valueOf(tableName));
        System.out.println(tableName + " is deleted!");
    }

    public static void main(String[] args) throws IOException {
        // 创建表
        String tableName = "blog";
        String[] family = { "article", "author" };
        createTable(tableName, family);
        // 为表添加数据
        String[] column1 = {"title", "content", "tag"};
        String[] value1 = {
            "Head First HBase",
            "HBase is the Hadoop database",
            "Hadoop, HBase, NoSQL"};
        String[] column2 = {"name", "nickname"};
        String[] value2 = {"nicholas", "lee"};
        String[] value3 = {"lilaoshi", "malaoshi"};
        addData("rowkey1", "blog", column1, value1, column2, value2);
        addData("rowkey1", "blog", column1, value1, column2, value3);
        addData("rowkey2", "blog", column1, value1, column2, value2);
        addData("rowkey3", "blog", column1, value1, column2, value2);
        // 遍历查询, 根据 row key 范围遍历查询
        getResultScan("blog", "rowkey2", "rowkey3");
        // 查询
        getResult("blog", "rowkey1");
        // 查询某一列的值
        getResultByColumn("blog", "rowkey1", "author", "name");
        // 更新列
        updateTable("blog", "rowkey1", "author", "name", "bin");
        // 查询某一列的值
        getResultByColumn("blog", "rowkey1", "author", "name");
        // 查询某列的多版本
        getResultByVersion("blog", "rowkey1", "author", "name");
        // 删除一列
        deleteOneColumnOfOneRow("blog", "rowkey1", "author", "nickname");
        // 删除所有列
        deleteAllColumnOfOneRow("blog", "rowkey1");
        // 删除表
//         deleteTable("blog");
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(HBase)