引入依賴
首先需要引入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();
}
}
}
}
基礎工具類
- 創建表
/**
* 創建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;
}
- 刪除表
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;
}
- 插入數據
/**
* 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;
}
- 獲取單條數據
/**
* 獲取單條數據
*
* @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;
}
- 通過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;
}
- 刪除行
/**
* 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;
}
- 刪除列族
/**
* 刪除列族
* @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;
}
- 刪除列
/**
* 刪除列
* @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;
}
基礎工具類測試
- 創建表
@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");
}
- 獲取一行數據
@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"))));
}
}
- 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();
}
- 刪除數據
@Test
public void deleteRow(){
HBaseUtil.deleteRow("FileTable","rowkey1");
}
- 刪除表
@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");
}
- RowFilter 行過濾器測試
scan獲取[rowkey1,rowkey3)
的數據到緩存,匹配行鍵值爲rowkey1
的行,打印輸出rowKey
和fileName
/**
* 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
- 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
- 列前綴過濾器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
- 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(自擬,且該部門存在子部門),刪除該部門信息,該部門所有(直接)子部門被調整到其他部門(自擬)中。
設計
- 存儲表設計
創建表dept
設置兩個列族
列族info,列deptName部門名稱,detail備註,
列族realation,列parent父部門編號 - rowKey設計
假定部門等級共4級。每個部門的子部門個數不超過100,用8位數字充當rowKey
一級部門編號爲xx000000 其中xx是一級部門的編號
二級部門編號爲xxyy0000 其中yy是一級部門的編號,yy是一級部門下的二級部門的編號
同理可得三級部門和四級部門的rowKey
這樣設計的好處:
- 長度原則:在假設情況下儘可能的將長度進行了壓縮,雖然不是最短,但是也是相對較短的了
- 唯一原則:在滿足假設的情況下,能保證rowkey的唯一
- 排序原則:RowKey是按照ASCII有序排序的,當查詢某個部門的子部門時,所有的子部門是依次排列在一起的,分散度較小,特別是查詢最低級部門時,查詢結果的rowKey是連續的,可以快速的查詢到子部門
- 散列原則:能做到均勻分佈,不容易出現熱點問題
編碼
- 創建表
/**
* 創建命名空間dept
* 創建表dept,列族info和parent
*/
@Test
public void createTable() {
HBaseUtil.createTable("dept:dept", new String[]{"info", "realation"});
}
- 插入數據
/**
* 按照規則插入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");
}
}
- 查詢頂級部門
/**
* 查詢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();
}
- 查詢所有直接子部門
/**
* 獲取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();
}
- 添加子部門
/**
* 在成都工務段下添加一個子部門
*/
@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");
}
- 刪除部門,將直接子部門轉到其他部門
/**
* 刪除部門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();
}
- 刪除表
/**
* 測試完畢,刪除表,方便下次直接使用
*/
@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");
}
}