HBase之JavaAPI

HBase提供了Java API的訪問接口,實際開發中我們經常用來操作HBase,就和我們通過java API操作RDBMS一樣。如下

API 作用
HBaseAdmin HBase 客戶端,用來操作HBase
Configuration 配置對象
Connection 連接對象
Table HBase 表對象
TableName HBase 中的表名
HTableDescriptor HBase 表描述信息對象
HColumnDescriptor HBase 列族描述對象
Put 用於插入數據
Get 用於查詢單條記錄
Delete 刪除數據對象
Scan 全表掃描對象,查詢所有記錄
ResultScanner 查詢數據返回結果集
Result 查詢返回的單條記錄結果
Cell 對應HBase中的列
SingleColumnValueFilter 列值過濾器(過濾列植的相等、不等、範圍等)
ColumnPrefixFilter 列名前綴過濾器(過濾指定前綴的列名)
multipleColumnPrefixFilter 多個列名前綴過濾器(過濾多個指定前綴的列名)
RowFilter rowKey 過濾器(通過正則,過濾rowKey值)

上面這些API,個人做了一個小Demo,代碼如下;

package com.cfl.hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * HBase Java API 操作
 * 一般我們使用Java API 主要操作的是數據即DML操作,DDL的操作較少
 */
public class HBaseTest {

    static Configuration conf = null;
    private Connection conn = null;
    private HBaseAdmin admin = null;
    private TableName tableName = null;
    private Table table = null;

    // 初始化配置
    @Before
    public void init() throws Exception {
        conf = HBaseConfiguration.create();
        // 如果不設置zookeeper地址,可以將hbase-site.xml文件複製到resource目錄下
        conf.set("hbase.zookeeper.quorum","node3,node4,node5");// zookeeper 地址
        // conf.set("hbase.zookeeper.property.clientPort","2188");// zookeeper 客戶端端口,默認爲2188,可以不用設置
        conn = ConnectionFactory.createConnection(conf);// 創建連接

        // admin = new HBaseAdmin(conf); // 已棄用,不推薦使用
        admin = (HBaseAdmin) conn.getAdmin(); // hbase 表管理類

        tableName = TableName.valueOf("students"); // 表名

        table = conn.getTable(tableName);// 表對象
    }

    // --------------------DDL 操作 Start------------------
    // 創建表 HTableDescriptor、HColumnDescriptor、addFamily()、createTable()
    @Test
    public void createTable() throws Exception {
        // 創建表描述類
        HTableDescriptor desc = new HTableDescriptor(tableName);

        // 添加列族info
        HColumnDescriptor family_info = new HColumnDescriptor("info");
        desc.addFamily(family_info);

        // 添加列族address
        HColumnDescriptor family_address = new HColumnDescriptor("address");
        desc.addFamily(family_address);

        // 創建表
        admin.createTable(desc);
    }

    // 刪除表 先棄用表disableTable(表名),再刪除表 deleteTable(表名)
    @Test
    public void deleteTable() throws Exception {
        admin.disableTable(tableName);
        admin.deleteTable(tableName);
    }

    // 添加列族 addColumn(表名,列族)
    @Test
    public void addFamily() throws Exception {
        admin.addColumn(tableName, new HColumnDescriptor("hobbies"));
    }

    // 刪除列族 deleteColumn(表名,列族)
    @Test
    public void deleteFamily() throws Exception {
        admin.deleteColumn(tableName, Bytes.toBytes("hobbies"));
    }

    // --------------------DDL 操作 End---------------------

    // ----------------------DML 操作 Start-----------------
    // 添加數據 Put(列族,列,列值)(HBase 中沒有修改,插入時rowkey相同,數據會覆蓋)
    @Test
    public void insertData() throws Exception {
        // 添加一條記錄
        // Put put = new Put(Bytes.toBytes("1001"));
        // put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("San-Qiang Zhang"));
        // put.addColumn(Bytes.toBytes("address"), Bytes.toBytes("province"), Bytes.toBytes("Hebei"));
        // put.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"), Bytes.toBytes("Shijiazhuang"));
        // table.put(put);

        // 添加多條記錄(批量插入)
        List<Put> putList = new ArrayList<Put>();
        Put put1 = new Put(Bytes.toBytes("1002"));
        put1.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("Lisi"));
        put1.addColumn(Bytes.toBytes("info"), Bytes.toBytes("sex"), Bytes.toBytes("1"));
        put1.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"), Bytes.toBytes("Shanghai"));
        Put put2 = new Put(Bytes.toBytes("1003"));
        put2.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name"), Bytes.toBytes("Lili"));
        put2.addColumn(Bytes.toBytes("info"), Bytes.toBytes("sex"), Bytes.toBytes("0"));
        put2.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"), Bytes.toBytes("Beijing"));
        Put put3 = new Put(Bytes.toBytes("1004"));
        put3.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name_a"), Bytes.toBytes("Zhaosi"));
        Put put4 = new Put(Bytes.toBytes("1004"));
        put4.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name_b"), Bytes.toBytes("Wangwu"));
        putList.add(put1);
        putList.add(put2);
        putList.add(put3);
        putList.add(put4);
        table.put(putList);
    }

    // 刪除數據 Delete
    @Test
    public void deleteData() throws Exception {
        // 刪除一條數據(行健爲1002)
        // Delete delete = new Delete(Bytes.toBytes("1002"));
        // table.delete(delete);

        // 刪除行健爲1003,列族爲info的數據
        // Delete delete = new Delete(Bytes.toBytes("1003"));
        // delete.addFamily(Bytes.toBytes("info"));
        // table.delete(delete);

        // 刪除行健爲1,列族爲address,列爲city的數據
        Delete delete = new Delete(Bytes.toBytes("1001"));
        delete.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"));
        table.delete(delete);
    }

    // 單條查詢 Get
    @Test
    public void getData() throws Exception {
        Get get = new Get(Bytes.toBytes("1001"));
        // get.addFamily(Bytes.toBytes("info")); //指定獲取某個列族
        // get.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name")); //指定獲取某個列族中的某個列
        Result result = table.get(get);

        System.out.println("行健:" + Bytes.toString(result.getRow()));
        byte[] name = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
        byte[] sex = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex"));
        byte[] city = result.getValue(Bytes.toBytes("address"), Bytes.toBytes("city"));
        byte[] province = result.getValue(Bytes.toBytes("address"), Bytes.toBytes("province"));
        if (name != null) System.out.println("姓名:" +  Bytes.toString( name));
        if (sex != null) System.out.println("性別:" +  Bytes.toString( sex));
        if (province != null) System.out.println("省份:" +  Bytes.toString(province));
        if (city != null) System.out.println("城市:" +  Bytes.toString(city));
    }

    // 全表掃描 Scan
    @Test
    public void scanData() throws Exception {
        Scan scan = new Scan(); // Scan 全表掃描對象
        // 行健是以字典序排序,可以使用scan.setStartRow(),scan.setStopRow()設置行健的字典序
        // scan.addFamily(Bytes.toBytes("info")); // 只查詢列族info
        //scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("name")); // 只查詢列name
        ResultScanner scanner = table.getScanner(scan);
        printResult1(scanner);
    }

    // 全表掃描:列值過濾器(過濾列植的相等、不等、範圍等) SingleColumnValueFilter
    @Test
    public void singleColumnValueFilter() throws Exception {
        /**
         * CompareOp 是一個枚舉,有如下幾個值
         * LESS                 小於
         * LESS_OR_EQUAL        小於或等於
         * EQUAL                等於
         * NOT_EQUAL            不等於
         * GREATER_OR_EQUAL     大於或等於
         * GREATER              大於
         * NO_OP                無操作
         */
        // 查詢列名大於San-Qiang Zhang的數據
        SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(
                                                            Bytes.toBytes("info"), Bytes.toBytes("name"),
                                                            CompareFilter.CompareOp.EQUAL, Bytes.toBytes("San-Qiang Zhang"));
        Scan scan = new Scan();
        scan.setFilter(singleColumnValueFilter);
        ResultScanner scanner = table.getScanner(scan);
        printResult1(scanner);
    }

    // 全表掃描:列名前綴過濾器(過濾指定前綴的列名) ColumnPrefixFilter
    @Test
    public void columnPrefixFilter() throws Exception {
        // 查詢列以name_開頭的數據
        ColumnPrefixFilter columnPrefixFilter = new ColumnPrefixFilter(Bytes.toBytes("name_"));
        Scan scan = new Scan();
        scan.setFilter(columnPrefixFilter);
        ResultScanner scanner = table.getScanner(scan);
        printResult1(scanner);
    }

    // 全表掃描:多個列名前綴過濾器(過濾多個指定前綴的列名) MultipleColumnPrefixFilter
    @Test
    public void multipleColumnPrefixFilter() throws Exception {
        // 查詢列以name_或c開頭的數據
        byte[][] bytes = new byte[][]{Bytes.toBytes("name_"), Bytes.toBytes("c")};
        MultipleColumnPrefixFilter multipleColumnPrefixFilter = new MultipleColumnPrefixFilter(bytes);
        Scan scan = new Scan();
        scan.setFilter(multipleColumnPrefixFilter);
        ResultScanner scanner = table.getScanner(scan);
        printResult1(scanner);
    }

    // rowKey過濾器(通過正則,過濾rowKey值) RowFilter
    @Test
    public void rowFilter() throws Exception {
        // 匹配rowkey以100開頭的數據
        // Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("^100"));
        // 匹配rowkey以2結尾的數據
        RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("2$"));
        Scan scan = new Scan();
        scan.setFilter(filter);
        ResultScanner scanner = table.getScanner(scan);
        printResult1(scanner);
    }

    // 多個過濾器一起使用
    @Test
    public void multiFilterTest() throws Exception {
        /**
         * Operator 爲枚舉類型,有兩個值 MUST_PASS_ALL 表示 and,MUST_PASS_ONE 表示 or
         */
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
        // 查詢性別爲0(nv)且 行健以10開頭的數據
        SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(
                                                        Bytes.toBytes("info"), Bytes.toBytes("sex"),
                                                        CompareFilter.CompareOp.EQUAL, Bytes.toBytes("0"));
        RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator("^10"));
        filterList.addFilter(singleColumnValueFilter);
        filterList.addFilter(rowFilter);
        Scan scan = new Scan();
        scan.setFilter(rowFilter);
        ResultScanner scanner = table.getScanner(scan);
        // printResult1(scanner);
        printResult2(scanner);
    }

    // --------------------DML 操作 End-------------------
    /** 打印查詢結果:方法一 */
    public void printResult1(ResultScanner scanner) throws Exception {
        for (Result result: scanner) {
            System.out.println("行健:" + Bytes.toString(result.getRow()));
            byte[] name = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
            byte[] sex = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("sex"));
            byte[] city = result.getValue(Bytes.toBytes("address"), Bytes.toBytes("city"));
            byte[] province = result.getValue(Bytes.toBytes("address"), Bytes.toBytes("province"));
            if (name != null) System.out.println("姓名:" +  Bytes.toString( name));
            if (sex != null) System.out.println("性別:" +  Bytes.toString( sex));
            if (province != null) System.out.println("省份:" +  Bytes.toString(province));
            if (city != null) System.out.println("城市:" +  Bytes.toString(city));
            System.out.println("------------------------------");
        }
    }

    /** 打印查詢結果:方法二 */
    public void printResult2(ResultScanner scanner) throws Exception {
        for (Result result: scanner) {
            System.out.println("-----------------------");
            // 遍歷所有的列及列值
            for (Cell cell : result.listCells()) {
                System.out.print(Bytes.toString(CellUtil.cloneQualifier(cell)) + ":");
                System.out.print(Bytes.toString(CellUtil.cloneValue(cell)) + "\t");
            }
            System.out.println();
            System.out.println("-----------------------");
        }
    }

    // 釋放資源
    @After
    public void destory() throws Exception {
        admin.close();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章