逐步掌握HBase的Java API常用操作

引入依賴

首先需要引入HBase相關依賴

		<dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>1.2.4</version>
        </dependency>

連接工具類

連接工具類需要設計成單例的,創建完成之後整個生命週期都可以使用

因爲獲取連接比較耗時,所以使用餓漢式一開始就創建了
定義兩個靜態的方法,分別用於獲取連接和獲取表

  • 針對表結構的操作,獲取連接進行操作
  • 針對表內的操作,可以直接獲取表進行操作
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Table;
import java.io.IOException;

/**
 * 〈獲取連接的單例的類〉
 * 因爲連接是貫穿整個操作的,所以採用餓漢式直接就創建了單例
 * 不常用的可以用靜態內部類,枚舉類或者雙重鎖創建懶漢式單例
 *
 * @author Chkl
 * @create 2020/5/5
 * @since 1.0.0
 */
public class HBaseConn {
    private static final HBaseConn INSTANCE = new HBaseConn();
    private static Configuration configuration;
    private static Connection connection;
	//構造方法中初始化連接配置
    private HBaseConn() {
        try {
            if (configuration == null) {
                configuration = HBaseConfiguration.create();
                configuration.set("hbase.zookeeper.quorum", "localhost");
                configuration.set("hbase.zookeeper.property.clientPort", "2181");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
	//通過工廠方法創建連接
    private Connection getConnection() {
        if (connection == null || connection.isClosed()) {
            try {
                connection = ConnectionFactory.createConnection(configuration);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return connection;
    }
	//獲取連接
    public static Connection getHBaseConn() {
        return INSTANCE.getConnection();
    }
	//獲取表對象
    public static Table getTable(String tableName) throws IOException {
        return INSTANCE.getConnection().getTable(TableName.valueOf(tableName));
    }
    //關閉連接
    public static void closeConn(){
        if (connection!=null){
            try {
                connection.close();
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

基礎工具類

  1. 創建表
	 /**
     * 創建Hbase表
     *
     * @param tableName 表名
     * @param cfs       列族數組
     * @return 是否創建成功
     */
    public static boolean createTable(String tableName, String[] cfs) {
        try (HBaseAdmin admin = (HBaseAdmin) HBaseConn.getHBaseConn().getAdmin()) {
            if (admin.tableExists(tableName)) {//表已經存在
                return false;
            }
            HTableDescriptor tableDescriptor =
                    new HTableDescriptor(TableName.valueOf(tableName));
            Arrays.stream(cfs).forEach(cf -> {//遍歷列族數組
                HColumnDescriptor columnDescriptor = new HColumnDescriptor(cf);
                columnDescriptor.setMaxVersions(1);//設置版本數量
                tableDescriptor.addFamily(columnDescriptor);
            });
            admin.createTable(tableDescriptor);//創建表
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
  1. 刪除表
	public static boolean deleteTable(String tableName){
        try (HBaseAdmin admin = (HBaseAdmin) HBaseConn.getHBaseConn().getAdmin()) {
            admin.disableTable(tableName);//disable表
            admin.deleteTable(tableName);//刪除表
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
  1. 插入數據
	/**
     * hbase中插入一條數據
     *
     * @param tableName 表名
     * @param rowKey    唯一標識
     * @param cfName    列族名
     * @param qualifier 列名
     * @param data      數據
     * @return 是否插入成功
     */
    public static boolean putRow(String tableName, String rowKey,
                                 String cfName, String qualifier, String data) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Put put = new Put(Bytes.toBytes(rowKey));//創建put對象
            put.addColumn(Bytes.toBytes(cfName),
                    Bytes.toBytes(qualifier),
                    Bytes.toBytes(data));//封裝put對象
            table.put(put);//put數據
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 插入多條數據
     *
     * @param tableName 表名
     * @param puts      封裝好的put集合
     * @return 是否成功
     */
    public static boolean putRows(String tableName, List<Put> puts) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            table.put(puts);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
  1. 獲取單條數據
 	/**
     * 獲取單條數據
     *
     * @param tableName 表名
     * @param rowKey    唯一標識
     * @return 查詢結果
     */
    public static Result getRow(String tableName, String rowKey) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Get get = new Get(Bytes.toBytes(rowKey));
            return table.get(get);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 獲取單條數據
     *
     * @param tableName  表名
     * @param rowKey     唯一標識
     * @param filterList 過濾器
     * @return 查詢結果
     */
    public static Result getRow(String tableName, String rowKey, FilterList filterList) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Get get = new Get(Bytes.toBytes(rowKey));
            get.setFilter(filterList);
            return table.get(get);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
  1. 通過scanner掃描表中數據
 	/**
     * 全表掃描
     *
     * @param tableName 表名
     * @return ResultScanner
     */
    public static ResultScanner getScanner(String tableName) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Scan scan = new Scan();
            scan.setCaching(1000);//緩存條數
            return table.getScanner(scan);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 帶過濾器的掃描
     * @param tableName 表名
     * @param filterList 過濾器
     * @return ResultScanner
     */
    public static ResultScanner getScanner(String tableName,FilterList filterList) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Scan scan = new Scan();
            scan.setCaching(1000);//緩存條數
            scan.setFilter(filterList);
            return table.getScanner(scan);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 按區間掃描
     * @param tableName 表名
     * @param startKey 起始rowkey
     * @param endKey 終止rowKey
     * @return ResultScanner
     */
    public static ResultScanner getScanner(String tableName, String startKey, String endKey) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Scan scan = new Scan();
            scan.setCaching(1000);//緩存條數
            scan.setStartRow(Bytes.toBytes(startKey));
            scan.setStopRow(Bytes.toBytes(endKey));
            return table.getScanner(scan);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *  帶過濾器的按區間掃描
     * @param tableName 表名
     * @param startKey 起始rowkey
     * @param endKey 終止rowKey
     * @param filterList 過濾器
     * @return ResultScanner
     */
    public static ResultScanner getScanner(String tableName, String startKey, String endKey,
                                           FilterList filterList) {
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Scan scan = new Scan();
            scan.setCaching(1000);//緩存條數
            scan.setStartRow(Bytes.toBytes(startKey));
            scan.setStopRow(Bytes.toBytes(endKey));
            scan.setFilter(filterList);
            return table.getScanner(scan);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
  1. 刪除行
	/**
     * hbase刪除一行記錄
     * @param tableName 表名
     * @param rowKey 唯一標識
     * @return 是否成功
     */
    public static boolean deleteRow(String tableName,String rowKey){
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Delete delete = new Delete(Bytes.toBytes(rowKey));
            table.delete(delete);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
  1. 刪除列族
	/**
     * 刪除列族
     * @param tableName 表名
     * @param cName 列族名
     * @return 是否成功
     */
    public static boolean deleteColumnFamily(String tableName,String cName){
        try (HBaseAdmin admin = (HBaseAdmin) HBaseConn.getHBaseConn().getAdmin()) {
           admin.deleteColumn(tableName,cName);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }
  1. 刪除列
	/**
     * 刪除列
     * @param tableName 表名
     * @param rowKey 唯一標識
     * @param cfName 列族名
     * @param qualifier 列名
     * @return
     */
    public static boolean deleteQualifier(String tableName,String rowKey,
                                          String cfName,String qualifier){
        try (Table table = HBaseConn.getTable(tableName)) {//創建table對象
            Delete delete = new Delete(Bytes.toBytes(rowKey));
            delete.addColumn(Bytes.toBytes(cfName),Bytes.toBytes(qualifier));
            table.delete(delete);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

基礎工具類測試

  1. 創建表
	@Test
    public void createTable() {
        HBaseUtil.createTable("FileTable", new String[]{"fileInfo", "saveInfo"});
    }
  1. 添加數據
	 @Test
    public void addFile() {
        HBaseUtil.putRow("FileTable", "rowkey1", "fileInfo", "name", "file1.txt");
        HBaseUtil.putRow("FileTable", "rowkey1", "fileInfo", "type", "txt");
        HBaseUtil.putRow("FileTable", "rowkey1", "fileInfo", "size", "1024");
        HBaseUtil.putRow("FileTable", "rowkey1", "saveInfo", "creater", "klchen");
    }
  1. 獲取一行數據
	 @Test
    public void getFileDetails() {
        Result result = HBaseUtil.getRow("FileTable", "rowkey1");
        if (result != null) {
            System.out.println("rowkey = "
                    + Bytes.toString(result.getRow()));
            System.out.println("fileName = "
                    + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
        }
    }
  1. scan掃描數據
	@Test
    public void scanFileDetails(){
        ResultScanner scanner = HBaseUtil.getScanner("FileTable", "rowkey1", "rowkey1");
        if (scanner!=null){
            scanner.forEach(result -> {
                System.out.println("rowkey = "
                        + Bytes.toString(result.getRow()));
                System.out.println("fileName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
            });
        }
        scanner.close();
    }
  1. 刪除數據
	@Test
    public void deleteRow(){
        HBaseUtil.deleteRow("FileTable","rowkey1");
    }
  1. 刪除表
	@Test
    public void deleteTable(){
        HBaseUtil.deleteTable("FileTable");
    }

HBase過濾器使用

基於結構的過濾器

  • 基於行的過濾器:
    • PrefixFilter 行前綴過濾器
    • PageFilter 基於行的分頁
  • 基於列的過濾器
    • ColumnPrefixFilter 列前綴匹配
    • FirstKeyOnlyFilter 只返回每一行的第一列
  • 基於單元格的過濾器
    • KeyOnlyFilter 返回的數據不包括單元格值,只包含行鍵與列
    • TimestampsFilter 根據數據的時間戳版本進行過濾
  • 基於列和單元值的過濾器
    • SingleColumnValueFilter 對列的單元值進行比較過濾
    • SingleColumnValueExcludeFilter 對列的單元值進行比較過濾

基於比較的過濾器

  • RowFilter 行過濾器
  • FamilyFilter 列族過濾器
  • QualifierFilter 列過濾器
  • ValueFilter 值過濾器

常用過濾器
在這裏插入圖片描述
針對上面創建的基礎工具類測試幾種常見的過濾器

首先創建表添加測試數據

	@Test
    public void createTable() {
        HBaseUtil.createTable("FileTable", new String[]{"fileInfo", "saveInfo"});
    }

    @Test
    public void addFile() {
        HBaseUtil.putRow("FileTable", "rowkey1", "fileInfo", "name", "file1.txt");
        HBaseUtil.putRow("FileTable", "rowkey1", "fileInfo", "type", "txt");
        HBaseUtil.putRow("FileTable", "rowkey1", "fileInfo", "size", "1024");
        HBaseUtil.putRow("FileTable", "rowkey1", "saveInfo", "creater", "klchen");

        HBaseUtil.putRow("FileTable", "rowkey2", "fileInfo", "name", "file2.txt");
        HBaseUtil.putRow("FileTable", "rowkey2", "fileInfo", "type", "txt");
        HBaseUtil.putRow("FileTable", "rowkey2", "fileInfo", "size", "2048");
        HBaseUtil.putRow("FileTable", "rowkey2", "saveInfo", "creater", "klchen");

        HBaseUtil.putRow("FileTable", "rowkey3", "fileInfo", "name", "file3.txt");
        HBaseUtil.putRow("FileTable", "rowkey3", "fileInfo", "type", "txt");
        HBaseUtil.putRow("FileTable", "rowkey3", "fileInfo", "size", "512");
        HBaseUtil.putRow("FileTable", "rowkey3", "saveInfo", "creater", "klchen");

        HBaseUtil.putRow("FileTable", "rowkey4", "fileInfo", "name", "file4.txt");
        HBaseUtil.putRow("FileTable", "rowkey4", "fileInfo", "type", "txt");
        HBaseUtil.putRow("FileTable", "rowkey4", "fileInfo", "size", "4096");
        HBaseUtil.putRow("FileTable", "rowkey4", "saveInfo", "creater", "klchen");

    }
  1. RowFilter 行過濾器測試
    scan獲取[rowkey1,rowkey3)的數據到緩存,匹配行鍵值爲rowkey1的行,打印輸出rowKeyfileName
	 /**
     * row過濾器,進行與rowkey相關的過濾
     * 可以大於,小於,大於等於,小於等於,等於
     */
    @Test
    public void rowFilterTest(){
        //行過濾器是基於比較的,所以添加一個比較規則
        RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("rowkey1")));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(filter));
        ResultScanner scanner = HBaseUtil.getScanner("FileTable", "rowkey1", "rowkey3", filterList);
        if (scanner!=null){
            scanner.forEach(result -> {
                System.out.println("rowkey = "
                        + Bytes.toString(result.getRow()));
                System.out.println("fileName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
            });
        }
        scanner.close();
    }

打印輸出:

rowkey = rowkey1
fileName = file1.txt
  1. PrefixFilter 行前綴過濾器
    匹配行鍵前綴爲rowkey1的行,預計只有一行
	/**
     * prefix過濾器,進行rowkey前綴爲某個值的過濾
     */
    @Test
    public void prefixFilterTest(){
        PrefixFilter filter = new PrefixFilter(Bytes.toBytes("rowkey2"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(filter));
        ResultScanner scanner = HBaseUtil.getScanner("FileTable", "rowkey1", "rowkey3", filterList);
        if (scanner!=null){
            scanner.forEach(result -> {
                System.out.println("rowkey = "
                        + Bytes.toString(result.getRow()));
                System.out.println("fileName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
            });
        }
        scanner.close();
    }

打印輸出:

rowkey = rowkey1
fileName = file1.txt
  1. 列前綴過濾器ColumnPrefixFilter
    獲取列前綴爲name的列的信息
    預測有兩行數據,其中只有name列有值,其他列沒有值
	/**
     * 列名前綴過濾器,過濾前綴爲指定值的列
     */
    @Test
    public void columnPrefixFilterTest(){
        ColumnPrefixFilter filter = new ColumnPrefixFilter(Bytes.toBytes("name"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(filter));
        ResultScanner scanner = HBaseUtil.getScanner("FileTable", "rowkey1", "rowkey3", filterList);
        if (scanner!=null){
            scanner.forEach(result -> {
                System.out.println("rowkey = "
                        + Bytes.toString(result.getRow()));
                System.out.println("fileName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
                System.out.println("filetype = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("type"))));
            });
        }
        scanner.close();
    }

打印輸出:

rowkey = rowkey1
fileName = file1.txt
filetype = null
rowkey = rowkey2
fileName = file2.txt
filetype = null
  1. KeyOnly過濾器
    匹配到之後只返回rowkey不返回單元格的值
	/**
     * KeyOnly過濾器,只返回rowkey的值不會返回實際存儲的內容
     */
    @Test
    public void keyOnlyFilterTest(){
        KeyOnlyFilter filter = new KeyOnlyFilter(true);
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(filter));
        ResultScanner scanner = HBaseUtil.getScanner("FileTable", "rowkey1", "rowkey3", filterList);
        if (scanner!=null){
            scanner.forEach(result -> {
                System.out.println("rowkey = "
                        + Bytes.toString(result.getRow()));
                System.out.println("fileName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
            });
        }
        scanner.close();
    }

打印輸出:
可以看到值有rowkey有值,單元格都沒有值

rowkey = rowkey1
fileName =    	
rowkey = rowkey2
fileName =

5.ValueFilter 值過濾器
獲取值爲file2.txt的單元格

	/**
     * 值過濾器,獲取值爲某值的一條值
     */
    @Test
    public void valueFilterTest(){
        ValueFilter filter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("file2.txt")));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(filter));
        ResultScanner scanner = HBaseUtil.getScanner("FileTable", "rowkey1", "rowkey3", filterList);
        if (scanner!=null){
            scanner.forEach(result -> {
                System.out.println("rowkey = "
                        + Bytes.toString(result.getRow()));
                System.out.println("fileName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("name"))));
                System.out.println("filetype = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("fileInfo"), Bytes.toBytes("type"))));
            });
        }
        scanner.close();
    }

打印輸出:
可以看出查詢到的是單元格而不是行,只能查詢出單元格的值

rowkey = rowkey2
fileName = file2.txt
filetype = null

綜合案例

要求
1.建立命名空間(命名空間名自擬)
2.在該命名空間中建立滿足以下要求的數據表(表名自擬)
3.在表中增加滿足業務場景描述的數據(不少於10條)
4.完成以下查詢操作

  • 查詢所有一級部門(沒有上級部門的部門)
  • 已知rowkey(自擬),查詢該部門的所有(直接)子部門信息
  • 已知rowkey(自擬),向該部門增加一個子部門
  • 已知rowkey(自擬,且該部門存在子部門),刪除該部門信息,該部門所有(直接)子部門被調整到其他部門(自擬)中。

設計

  1. 存儲表設計
    創建表dept
    設置兩個列族
    列族info,列deptName部門名稱,detail備註,
    列族realation,列parent父部門編號
  2. rowKey設計
    假定部門等級共4級。每個部門的子部門個數不超過100,用8位數字充當rowKey
    一級部門編號爲xx000000 其中xx是一級部門的編號
    二級部門編號爲xxyy0000 其中yy是一級部門的編號,yy是一級部門下的二級部門的編號
    同理可得三級部門和四級部門的rowKey
    這樣設計的好處:
  1. 長度原則:在假設情況下儘可能的將長度進行了壓縮,雖然不是最短,但是也是相對較短的了
  2. 唯一原則:在滿足假設的情況下,能保證rowkey的唯一
  3. 排序原則:RowKey是按照ASCII有序排序的,當查詢某個部門的子部門時,所有的子部門是依次排列在一起的,分散度較小,特別是查詢最低級部門時,查詢結果的rowKey是連續的,可以快速的查詢到子部門
  4. 散列原則:能做到均勻分佈,不容易出現熱點問題

編碼

  1. 創建表
	/**
     * 創建命名空間dept
     * 創建表dept,列族info和parent
     */
    @Test
    public void createTable() {
        HBaseUtil.createTable("dept:dept", new String[]{"info", "realation"});
    }
  1. 插入數據
	/**
     * 按照規則插入207條數據
     */
    @Test
    public void addRows() {
        //添加2個頂級部門
        HBaseUtil.putRow("dept:dept", "10000000", "info", "deptName", "成都鐵路局");
        HBaseUtil.putRow("dept:dept", "10000000", "info", "detail", "頂級部門");
        HBaseUtil.putRow("dept:dept", "10000000", "realation", "parent", "");

        HBaseUtil.putRow("dept:dept", "12000000", "info", "deptName", "鄭州鐵路局");
        HBaseUtil.putRow("dept:dept", "12000000", "info", "detail", "頂級部門");
        HBaseUtil.putRow("dept:dept", "12000000", "realation", "parent", "");

        //添加三個2級部門
        HBaseUtil.putRow("dept:dept", "10100000", "info", "deptName", "綿陽工務段");
        HBaseUtil.putRow("dept:dept", "10100000", "info", "detail", "工務段級");
        HBaseUtil.putRow("dept:dept", "10100000", "realation", "parent", "10000000");

        HBaseUtil.putRow("dept:dept", "10130000", "info", "deptName", "達州工務段");
        HBaseUtil.putRow("dept:dept", "10130000", "info", "detail", "工務段級");
        HBaseUtil.putRow("dept:dept", "10130000", "realation", "parent", "10000000");

        HBaseUtil.putRow("dept:dept", "10010000", "info", "deptName", "成都工務段");
        HBaseUtil.putRow("dept:dept", "10010000", "info", "detail", "工務段級");
        HBaseUtil.putRow("dept:dept", "10010000", "realation", "parent", "10000000");

        //在綿陽工務段下創建2個三級部門
        HBaseUtil.putRow("dept:dept", "10100600", "info", "deptName", "江油線路車間");
        HBaseUtil.putRow("dept:dept", "10100600", "info", "detail", "'線路車間");
        HBaseUtil.putRow("dept:dept", "10100600", "realation", "parent", "10100000");

        HBaseUtil.putRow("dept:dept", "10100700", "info", "deptName", "樂壩線路車間");
        HBaseUtil.putRow("dept:dept", "10100700", "info", "detail", "'線路車間");
        HBaseUtil.putRow("dept:dept", "10100700", "realation", "parent", "10100000");

        //在江油線路車間下創建100個四級部門
        for (int i = 0; i < 10; i++) {
            HBaseUtil.putRow("dept:dept", "1010060" + i, "info", "deptName", "江油線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "1010060" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "1010060" + i, "realation", "parent", "10100600");
        }
        for (int i = 10; i < 100; i++) {
            HBaseUtil.putRow("dept:dept", "101006" + i, "info", "deptName", "江油線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "101006" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "101006" + i, "realation", "parent", "10100600");
        }
        //在樂壩線路車間下創建100個四級部門
        for (int i = 0; i < 10; i++) {
            HBaseUtil.putRow("dept:dept", "1010070" + i, "info", "deptName", "樂壩線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "1010070" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "1010070" + i, "realation", "parent", "10100700");
        }
        for (int i = 10; i < 100; i++) {
            HBaseUtil.putRow("dept:dept", "101007" + i, "info", "deptName", "樂壩線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "101007" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "101007" + i, "realation", "parent", "10100700");
        }
    }
  1. 查詢頂級部門
	/**
     * 查詢parent列值爲""的行爲頂級部門
     * 同時使用值過濾器和列前綴過濾器
     */
    @Test
    public void selectTopDept() {
        ValueFilter valuefilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("")));
        ColumnPrefixFilter columnfilter = new ColumnPrefixFilter(Bytes.toBytes("parent"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(valuefilter, columnfilter));
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", filterList);
        if (scanner != null) {
            scanner.forEach(result -> {
                Result row = HBaseUtil.getRow("dept:dept", Bytes.toString(result.getRow()));
                System.out.print("rowkey = "
                        + Bytes.toString(row.getRow())+" , ");
                System.out.print("deptName = "
                        + Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("deptName")))+" , ");
                System.out.println("detail = "
                        + Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("detail"))));
            });
        }
        scanner.close();
    }
  1. 查詢所有直接子部門
  /**
     * 獲取10100600部門的所有子級部門信息
     */
    @Test
    public void selectChildren(){
        ValueFilter valuefilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("10100600")));
        ColumnPrefixFilter columnfilter = new ColumnPrefixFilter(Bytes.toBytes("parent"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(valuefilter, columnfilter));
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", filterList);
        if (scanner != null) {
            scanner.forEach(result -> {
                Result row = HBaseUtil.getRow("dept:dept", Bytes.toString(result.getRow()));
                System.out.print("rowkey = "
                        + Bytes.toString(row.getRow())+" , ");
                System.out.print("deptName = "
                        + Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("deptName")))+" , ");
                System.out.println("detail = "
                        + Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("detail"))));
            });
        }
        scanner.close();
    }

如果直接子部門時最低級部門時,可以不使用filter

	/**
     * 獲取10100600部門的所有子級部門信息
     * 只針對直接子部門時最低一級的部門有效
     * 不用filter  直接獲取區間內的sacn就可以了   快了很多!
     */
    @Test
    public void selectChildren2(){
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", "10100600","10100700");
        if (scanner != null) {
            scanner.forEach(result -> {
                System.out.print("rowkey = "
                        + Bytes.toString(result.getRow())+" , ");
                System.out.print("deptName = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("deptName")))+" , ");
                System.out.println("detail = "
                        + Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("detail"))));
            });
        }
        scanner.close();
    }
  1. 添加子部門
	 /**
     * 在成都工務段下添加一個子部門
     */
    @Test
    public void addChild(){
        HBaseUtil.putRow("dept:dept", "10010900", "info", "deptName", "雙流線路車間");
        HBaseUtil.putRow("dept:dept", "10010900", "info", "detail", "線路車間");
        HBaseUtil.putRow("dept:dept", "10010900", "realation", "parent", "10010000");
    }
  1. 刪除部門,將直接子部門轉到其他部門
 	 /**
     * 刪除部門10100600 ,將所有下級部門轉給10100700
     */
    @Test
    public void deleteDept(){
        //刪除部門10100600
        HBaseUtil.deleteRow("dept:dept","10100600");
        //將10100600的所有直接子部門轉給10100700
        ValueFilter valuefilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("10100600")));
        ColumnPrefixFilter columnfilter = new ColumnPrefixFilter(Bytes.toBytes("parent"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(valuefilter, columnfilter));
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", filterList);
        if (scanner != null) {
            scanner.forEach(result -> {
                //hbase中沒有修改操作,先刪除後添加
                HBaseUtil.deleteQualifier("dept:dept",Bytes.toString(result.getRow()), "realation", "parent");
                HBaseUtil.putRow("dept:dept", Bytes.toString(result.getRow()), "realation", "parent", "10100700");
            });
        }
        scanner.close();
    }
  1. 刪除表
	/**
     * 測試完畢,刪除表,方便下次直接使用
     */
    @Test
    public void deleteTable() {
        HBaseUtil.deleteTable("dept:dept");
    }

改寫成接口

爲了讓數據和操作能在界面上顯示,將單元測試改寫成接口

創建一個Spring Boot工程,添加web依賴

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

編寫接口實現

/**
 * 〈dept綜合用例調用接口〉
 *
 * @author Chkl
 * @create 2020/5/5
 * @since 1.0.0
 */
@RestController
public class DeptController {

    /**
     * 創建命名空間dept
     * 創建表dept,列族info和parent
     */
    @RequestMapping("createTable")
    public void createTable() {
        HBaseUtil.createTable("dept:dept", new String[]{"info", "realation"});
    }

    /**
     * 按照規則插入207條數據
     */
    @RequestMapping("addRows")
    public void addRows() {
        //添加2個頂級部門
        HBaseUtil.putRow("dept:dept", "10000000", "info", "deptName", "成都鐵路局");
        HBaseUtil.putRow("dept:dept", "10000000", "info", "detail", "頂級部門");
        HBaseUtil.putRow("dept:dept", "10000000", "realation", "parent", "");

        HBaseUtil.putRow("dept:dept", "12000000", "info", "deptName", "鄭州鐵路局");
        HBaseUtil.putRow("dept:dept", "12000000", "info", "detail", "頂級部門");
        HBaseUtil.putRow("dept:dept", "12000000", "realation", "parent", "");

        //添加三個2級部門
        HBaseUtil.putRow("dept:dept", "10100000", "info", "deptName", "綿陽工務段");
        HBaseUtil.putRow("dept:dept", "10100000", "info", "detail", "工務段級");
        HBaseUtil.putRow("dept:dept", "10100000", "realation", "parent", "10000000");

        HBaseUtil.putRow("dept:dept", "10130000", "info", "deptName", "達州工務段");
        HBaseUtil.putRow("dept:dept", "10130000", "info", "detail", "工務段級");
        HBaseUtil.putRow("dept:dept", "10130000", "realation", "parent", "10000000");

        HBaseUtil.putRow("dept:dept", "10010000", "info", "deptName", "成都工務段");
        HBaseUtil.putRow("dept:dept", "10010000", "info", "detail", "工務段級");
        HBaseUtil.putRow("dept:dept", "10010000", "realation", "parent", "10000000");

        //在綿陽工務段下創建2個三級部門
        HBaseUtil.putRow("dept:dept", "10100600", "info", "deptName", "江油線路車間");
        HBaseUtil.putRow("dept:dept", "10100600", "info", "detail", "'線路車間");
        HBaseUtil.putRow("dept:dept", "10100600", "realation", "parent", "10100000");

        HBaseUtil.putRow("dept:dept", "10100700", "info", "deptName", "樂壩線路車間");
        HBaseUtil.putRow("dept:dept", "10100700", "info", "detail", "'線路車間");
        HBaseUtil.putRow("dept:dept", "10100700", "realation", "parent", "10100000");

        //在江油線路車間下創建100個四級部門
        for (int i = 0; i < 10; i++) {
            HBaseUtil.putRow("dept:dept", "1010060" + i, "info", "deptName", "江油線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "1010060" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "1010060" + i, "realation", "parent", "10100600");
        }
        for (int i = 10; i < 100; i++) {
            HBaseUtil.putRow("dept:dept", "101006" + i, "info", "deptName", "江油線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "101006" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "101006" + i, "realation", "parent", "10100600");
        }
        //在樂壩線路車間下創建100個四級部門
        for (int i = 0; i < 10; i++) {
            HBaseUtil.putRow("dept:dept", "1010070" + i, "info", "deptName", "樂壩線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "1010070" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "1010070" + i, "realation", "parent", "10100700");
        }
        for (int i = 10; i < 100; i++) {
            HBaseUtil.putRow("dept:dept", "101007" + i, "info", "deptName", "樂壩線路車間測試工區" + i);
            HBaseUtil.putRow("dept:dept", "101007" + i, "info", "detail", "'線路工間");
            HBaseUtil.putRow("dept:dept", "101007" + i, "realation", "parent", "10100700");
        }
    }

    /**
     * 查詢parent列值爲""的行爲頂級部門
     * 同時使用值過濾器和列前綴過濾器
     */
    @RequestMapping("selectTopDept")
    public Object selectTopDept() {
        ValueFilter valuefilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes("")));
        ColumnPrefixFilter columnfilter = new ColumnPrefixFilter(Bytes.toBytes("parent"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(valuefilter, columnfilter));
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", filterList);
        List<DeptVo> res = new ArrayList<>();
        if (scanner != null) {
            scanner.forEach(result -> {
                Result row = HBaseUtil.getRow("dept:dept", Bytes.toString(result.getRow()));
                DeptVo deptVo = new DeptVo();
                deptVo.setRowkey(Bytes.toString(row.getRow()));
                deptVo.setDeptName(Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("deptName"))));
                deptVo.setDetail(Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("detail"))));
                res.add(deptVo);
            });
        }
        scanner.close();
        return res;
    }

    /**
     * 獲取10100600部門的所有子級部門信息
     */
    @RequestMapping("selectChildren/{rowkey}")
    public Object selectChildren(@PathVariable String rowkey) {
        ValueFilter valuefilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(rowkey)));
        ColumnPrefixFilter columnfilter = new ColumnPrefixFilter(Bytes.toBytes("parent"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(valuefilter, columnfilter));
        List<DeptVo> res = new ArrayList<>();
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", filterList);
        if (scanner != null) {
            scanner.forEach(result -> {
                Result row = HBaseUtil.getRow("dept:dept", Bytes.toString(result.getRow()));
                DeptVo deptVo = new DeptVo();
                deptVo.setRowkey(Bytes.toString(row.getRow()));
                deptVo.setDeptName(Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("deptName"))));
                deptVo.setDetail(Bytes.toString(row.getValue(Bytes.toBytes("info"), Bytes.toBytes("detail"))));
                res.add(deptVo);
            });
        }
        scanner.close();
        return res;
    }



    /**
     * 在成都工務段下添加一個子部門
     */
    @RequestMapping("addChild")
    public void addChild(@RequestBody Dept dept) {
        HBaseUtil.putRow("dept:dept", dept.getRowkey(), "info", "deptName", dept.getDeptName());
        HBaseUtil.putRow("dept:dept", dept.getRowkey(), "info", "detail", dept.getDetail());
        HBaseUtil.putRow("dept:dept", dept.getRowkey(), "realation", "parent", dept.getParent());
    }

    /**
     * 刪除部門10100600 ,將所有下級部門轉給10100700
     */
    @RequestMapping("deleteDept/deleteDept/{deleteDept}/toDept/{toDept}")
    public void deleteDept(@PathVariable String deleteDept,
                           @PathVariable String toDept) {
        //刪除部門10100600
        HBaseUtil.deleteRow("dept:dept", deleteDept);
        //將10100600的所有直接子部門轉給10100700
        ValueFilter valuefilter = new ValueFilter(CompareFilter.CompareOp.EQUAL, new BinaryComparator(Bytes.toBytes(deleteDept)));
        ColumnPrefixFilter columnfilter = new ColumnPrefixFilter(Bytes.toBytes("parent"));
        //創建一個FilterList,設置規則爲必須全部filter都通過纔算通過
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL, Arrays.asList(valuefilter, columnfilter));
        ResultScanner scanner = HBaseUtil.getScanner("dept:dept", filterList);
        if (scanner != null) {
            scanner.forEach(result -> {
                //hbase中沒有修改操作,先刪除後添加
                HBaseUtil.deleteQualifier("dept:dept", Bytes.toString(result.getRow()), "realation", "parent");
                HBaseUtil.putRow("dept:dept", Bytes.toString(result.getRow()), "realation", "parent", toDept);
            });
        }
        scanner.close();
    }

    /**
     * 測試完畢,刪除表,方便下次直接使用
     */
    @RequestMapping("deleteTable")
    public void deleteTable() {
        HBaseUtil.deleteTable("dept:dept");
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章