6 需求三:查看一条数据
查询rowkey为4944191的所有列的数据,并打印出来。
实现步骤:
- 获取HTable
- 使用rowkey构建Get对象
- 执行get请求
- 获取所有单元格
- 打印rowkey
- 迭代单元格列表
- 关闭表
参考代码:
@Test public void getOneTest() throws IOException { // 1. 获取HTable TableName waterBillTableName = TableName.valueOf("WATER_BILL"); Table waterBilltable = connection.getTable(waterBillTableName); // 2. 使用rowkey构建Get对象 Get get = new Get(Bytes.toBytes("4944191")); // 3. 执行get请求 Result result = waterBilltable.get(get); // 4. 获取所有单元格 List<Cell> cellList = result.listCells(); // 打印rowkey System.out.println("rowkey => " + Bytes.toString(result.getRow())); // 5. 迭代单元格列表 for (Cell cell : cellList) { // 打印列蔟名 System.out.print(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength())); System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength())); } // 6. 关闭表 waterBilltable.close(); }
7 需求四:删除一条数据
删除rowkey为4944191的整条数据。
实现步骤:
- 获取HTable对象
- 根据rowkey构建delete对象
- 执行delete请求
- 关闭表
参考代码:
// 删除rowkey为4944191的整条数据 @Test public void deleteOneTest() throws IOException { // 1. 获取HTable对象 Table waterBillTable = connection.getTable(TableName.valueOf("WATER_BILL")); // 2. 根据rowkey构建delete对象 Delete delete = new Delete(Bytes.toBytes("4944191")); // 3. 执行delete请求 waterBillTable.delete(delete); // 4. 关闭表 waterBillTable.close(); }
8 需求五:导入数据
8.1 需求
在资料中,有一份10W的抄表数据文件,我们需要将这里面的数据导入到HBase中。
8.2 Import JOB
在HBase中,有一个Import的MapReduce作业,可以专门用来将数据文件导入到HBase中。
用法
hbase org.apache.hadoop.hbase.mapreduce.Import 表名 HDFS数据文件路径
8.3 导入数据
将资料中数据文件上传到Linux中
再将文件上传到hdfs中
hadoop fs -mkdir -p /water_bill/output_ept_10W
hadoop fs -put part-m-00000_10w /water_bill/output_ept_10W
启动YARN集群
start-yarn.sh
使用以下方式来进行数据导入
hbase org.apache.hadoop.hbase.mapreduce.Import WATER_BILL /water_bill/output_ept_10W
8.4 导出数据
hbase org.apache.hadoop.hbase.mapreduce.Export WATER_BILL
/water_bill/output_ept_10W_export
9 需求六:查询2020年6月份所有用户的用水量
9.1 需求分析
在Java API中,我们也是使用scan + filter来实现过滤查询。2020年6月份其实就是从2020年6月1
日到2020年6月30日的所有抄表数据。
9.2 准备工作
- 在cn.itcast.hbase.data.api_test包下创建ScanFilterTest类
- 使用@BeforeTest、@AfterTest构建HBase连接、以及关闭HBase连接
9.3 实现
实现步骤:
- 获取表
- 构建scan请求对象
- 构建两个过滤器
a) 构建两个日期范围过滤器(注意此处请使用RECORD_DATE——抄表日期比较
b) 构建过滤器列表
- 执行scan扫描请求
- 迭代打印result
- 迭代单元格列表
- 关闭ResultScanner(这玩意把转换成一个个的类似get的操作,注意要关闭释放资源)
- 关闭表
参考代码:
// 查询2020年6月份所有用户的用水量数据 @Test public void queryTest1() throws IOException { // 1. 获取表 Table waterBillTable = connection.getTable(TableName.valueOf("WATER_BILL")); // 2. 构建scan请求对象 Scan scan = new Scan(); // 3. 构建两个过滤器 // 3.1 构建日期范围过滤器(注意此处请使用RECORD_DATE——抄表日期比较 SingleColumnValueFilter startDateFilter = new SingleColumnValueFilter(Bytes.toBytes("C1") , Bytes.toBytes("RECORD_DATE") , CompareOperator.GREATER_OR_EQUAL , Bytes.toBytes("2020-06-01")); SingleColumnValueFilter endDateFilter = new SingleColumnValueFilter(Bytes.toBytes("C1") , Bytes.toBytes("RECORD_DATE") , CompareOperator.LESS_OR_EQUAL , Bytes.toBytes("2020-06-30")); // 3.2 构建过滤器列表 FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL , startDateFilter , endDateFilter); scan.setFilter(filterList); // 4. 执行scan扫描请求 ResultScanner resultScan = waterBillTable.getScanner(scan); // 5. 迭代打印result for (Result result : resultScan) { System.out.println("rowkey -> " + Bytes.toString(result.getRow())); System.out.println("------"); List<Cell> cellList = result.listCells(); // 6. 迭代单元格列表 for (Cell cell : cellList) { // 打印列蔟名 System.out.print(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength())); System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength())); } System.out.println("------"); } resultScanner.close(); // 7. 关闭表 waterBillTable.close(); }
9.4 解决乱码问题
因为前面我们的代码,在打印所有的列时,都是使用字符串打印的,Hbase中如果存储的是int、
double,那么有可能就会乱码了。
System.out.print(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength())); System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
要解决的话,我们可以根据列来判断,使用哪种方式转换字节码。如下:
- NUM_CURRENT
- NUM_PREVIOUS
- NUM_USAGE
- TOTAL_MONEY
这4列使用double类型展示,其他的使用string类型展示。
参考代码:
String colName = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()); System.out.print(colName); if(colName.equals("NUM_CURRENT") || colName.equals("NUM_PREVIOUS") || colName.equals("NUM_USAGE") || colName.equals("TOTAL_MONEY")) { System.out.println(" => " + Bytes.toDouble(cell.getValueArray(), cell.getValueOffset())); } else { System.out.println(" => " + Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength())); }
10 # hbase KeyValue结构打印
10.1表内容
hbase(main):003:0> scan ‘tableCreateTest1’
ROW | COLUMN+CELL |
row1 | column=cf1:name, timestamp=1467639285495, value=zq |
1 row(s) in 0.0210 seconds
10.2 KeyValue
1.片段代码
Get get = new Get(Bytes.toBytes("row1")); try { Result rs = ht.get(get); System.out.println("result size: " + rs.size()); System.out.println("result.toString: " + rs.toString()); KeyValue kv = rs.getColumnLatest(Bytes.toBytes("cf1"), Bytes.toBytes("name")); System.out.println("kv key: " + Bytes.toString(kv.getKey())); System.out.println("kv key: " + kv.getKeyString()); System.out.println("kv key: " + KeyValue.keyToString(kv.getKey())); System.out.println("kv row: " + Bytes.toString(kv.getRow())); System.out.println("kv family: " + Bytes.toString(kv.getFamily())); System.out.println("kv qualifier: " + Bytes.toString(kv.getQualifier())); System.out.println("kv timestam: " + String.valueOf(kv.getTimestamp())); System.out.println("kv value: " + Bytes.toString(kv.getValue())); } catch (IOException e) { e.printStackTrace(); }
2.结果
result size: 1 result.toString: keyvalues={row1/cf1:name/1467639285495/Put/vlen=2/mvcc=0} kv key: row1cf1nameU�F� kv key:\x00\x04row1\x03cf1name\x00\x00\x01U\xB61\x1B\xF1\x04 kv key: row1/cf1:name/1467639285495/Put kv row: row1 kv family: cf1 kv qualifier: name kv timestam: 1467639285495 kv value: zq