引入依赖
首先需要引入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");
}
}