Hbase高手之路 – 第五章 – HBase的Java API编程

一、 需求与数据集

某自来水公司,需要存储大量的缴费明细数据,以下截取了缴费明细的一部分内容:
在这里插入图片描述
因为缴费明细的数据记录非常庞大,该公司的信息部门决定使用hbase来存储这些数据,并且可以使用java来访问这些数据。

二、 准备工作

idea2021.3.3 专业版 (社区版也可以)

1. 下载安装idea

在这里插入图片描述

2. 配置国内的maven镜像库

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3. 创建一个maven工程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

4. 修改pom文件,导入相关的依赖

在这里插入图片描述

5. 复制HBase的配置文件hbase-site.xml到resources目录中

先导出到本地计算

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

6. 创建包结构

在这里插入图片描述
在这里插入图片描述

7. 创建hbase连接类及管理对象

在这里插入图片描述

public class HbaseConnect {
    public static void main(String[] args){
        //1、创建hbase的配置
        Configuration configuration = HBaseConfiguration.create();
        //2、创建hbase的连接
        Connection connection;

        {
            try {
                connection = ConnectionFactory.createConnection(configuration);
                System.out.println(connection);
                //3、创建admin对象
                Admin admin = connection.getAdmin();
                System.out.println(admin);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

在这里插入图片描述

三、 案例一、使用java api创建hbase的表

创建一个名为water_bill的表,包含一个列簇info。

1. 编写代码

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;

public class HbaseJavaAPIDemo2 {
    public static void main(String[] args) throws IOException {
        Configuration configuration = HBaseConfiguration.create();
        // 2.	使用ConnectionFactory.createConnection()创建Hbase连接
        Connection connection = ConnectionFactory.createConnection(configuration);
        Admin admin = null;
        {
            try {
                //通过工厂模式,根据配置来创建连接
                connection = ConnectionFactory.createConnection(configuration);
                System.out.println(connection);
                //3.创建admin对象
                admin = connection.getAdmin();
                System.out.println(admin);
                //4.创建water_bill的表,包含一个列簇info
                //定义表名
                TableName tableName = TableName.valueOf("WATER_BILL3");
                // 1) 构建表描述构建器构建器模式
                TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tableName);
                // 2)构建列簇描述构建器
                ColumnFamilyDescriptorBuilder columnFamilyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("info"));
                // 3)定义列簇描述对象
                ColumnFamilyDescriptor columnFamilyDescriptor = columnFamilyDescriptorBuilder.build();
                // 4)表描述构建器和列簇描述对象建立关系
                tableDescriptorBuilder.setColumnFamily(columnFamilyDescriptor);
                // 5)定义表描述对象
                TableDescriptor tableDescriptor = tableDescriptorBuilder.build();
                // 6)创建表
                admin.createTable(tableDescriptor);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                assert admin != null;
                admin.close();
                connection.close();
            }
        }
    }
}

2. 运行

在这里插入图片描述

3. 查看结果

在这里插入图片描述

四、 案例二:使用java api删除表

删除刚刚创建的表

1. 编写代码

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;


public class HbaseJavaAPIMain {
    public static void main(String[] args) throws IOException {
        Admin admin = getAdmin();
        //调用删除表的方法
        boolean result = deleteTable(admin,"WATER_BILL");
        if(result) {
            System.out.println("删除成功");
        }else {
            System.out.println("表不存在");
        }
        //调用插入数据的方法
//        putTable(admin.getConnection(),"WATER_BILL3","4944191","info","name","张三");
//        关闭admin
        admin.close();
    }
    public static Admin getAdmin() {
        //1.创建hbase配置
        Configuration configuration = HBaseConfiguration.create();
        // 2.	使用ConnectionFactory.createConnection()创建Hbase连接
        Connection connection;
        Admin admin =null;
        try {
            //通过工厂模式,根据配置来创建连接
            connection = ConnectionFactory.createConnection(configuration);
            //创建admin对象
            admin = connection.getAdmin();
        }catch (IOException e){
            e.printStackTrace();
        }
        return admin;
    }

    /**
     * 向表中插入数据
     * @param connection
     * @param tableName
     * @param haha
     * @param columnFamily
     * @param column
     * @param value
     * @throws IOException
     */
    public static void putTable(Connection connection,String tableName,String haha,String columnFamily,String column,String value) throws IOException {
        //获取table对象
        Table table = connection.getTable(TableName.valueOf(tableName));
        //根据 rowkey 获取Put对象
        Put put = new Put(Bytes.toBytes(haha));
        //添加姓名列
        put.addColumn(Bytes.toBytes(columnFamily),Bytes.toBytes(column),Bytes.toBytes(value));
        //插入数据
        table.put(put);
        //关闭table
        table.close();

    }

    /**
     * 删除表
     * @param admin
     * @param name
     * @return
     * @throws IOException
     */
    public static boolean deleteTable(Admin admin,String name)throws IOException {
        //定义表名
        TableName tableName = TableName.valueOf(name);
        //判断表是否存在
        if (admin.tableExists(tableName)) {
            //禁用表
            admin.disableTable(tableName);
            //删除表
            admin.deleteTable(tableName);
            return  true;
        } else {
            return false;
        }

    }
}

在这里插入图片描述

2. 查看结果

在这里插入图片描述

五、 案例三:向创建的表中插入数据

向WATER_BILL中插入姓名列的数据

1. 编写代码

在这里插入图片描述

2. 调用方法

在这里插入图片描述

3. 查看结果

在这里插入图片描述

六、 案例:插入其他列的数据

插入地址列的数据

1. 编写代码

在这里插入图片描述

2. 调用方法

在这里插入图片描述

3. 查看结果

在这里插入图片描述

七、 案例四:查看一条数据

查询显示rowkey为4944191的所有列的数据

1. 编写方法

(1) 获取某列的值

在这里插入图片描述

(2) 获取某行的数据

在这里插入图片描述

2. 调用方法

在这里插入图片描述

八、 案例五:导入数据

1. 需求

有一份10w条记录的抄表数据文件,需要将其导入hbase中
在这里插入图片描述

2. import job导入大量数据

在hbase中,有一个import的MR作业,可以专门用来将数据导入到hbase中
用法:
hbase org.apache.hadoop.hbase.mapreduce.import 表名 hdfs 数据文件路径

3. 上传数据到hdfs

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4. 导入数据

(1) 启动yarn
(2) 创建表

在这里插入图片描述

(3) 运行导入命令
hbase org.apache.hadoop.hbase.mapreduce.Import WATER_BILL /water_bill/

运行结果如下

在这里插入图片描述

(4) 查看数据

在这里插入图片描述

(5) count计数

在这里插入图片描述

(6) mapreduce计数
hbase org.apache.hadoop.hbase.mapreduce.RowCounter "WATER_BILL"

在这里插入图片描述

九、 案例六:查询2020年6月所有用户的用水量

1. 需求分析

在hbase中用scan+filter实现过滤查询。2020年6月份其实就是从2020年6月1号到2020年6月30日的所有抄表数据

2. 编写代码

public static void queryTable(Connection connection,String tableName,String columnFamily, String column,String startValue,String endValue)throws IOException {
        //1.获取Table
        Table table = connection.getTable(TableName.valueOf(tableName));
        //2.构建scan对象
        Scan scan = new Scan();
        //3.1构建过滤器
        //构建日期范围的过滤器
//        构建开始日期的过滤器
        SingleColumnValueFilter startDateFilter = new SingleColumnValueFilter(Bytes.toBytes(columnFamily),Bytes.toBytes(column),
                CompareOperator.GREATER_OR_EQUAL,Bytes.toBytes(startValue));
        //构建结束日期的过滤器
        SingleColumnValueFilter endDateFilter = new SingleColumnValueFilter(Bytes.toBytes(columnFamily),Bytes.toBytes(column),
                CompareOperator.LESS_OR_EQUAL,Bytes.toBytes(endValue));
        //3.2构建过滤器列表
        FilterList filterlist = new FilterList(FilterList.Operator.MUST_PASS_ALL,startDateFilter,endDateFilter);
        //4.构建扫描器
        scan.setFilter(filterlist);
        //5.执行scan扫描操作
        ResultScanner resultScanner = table.getScanner(scan);
        //6.迭代打印result
        for(Result result:resultScanner){
            // 6.1打印rowkey
            System.out.println("rowkey=>" + Bytes.toString(result.getRow()));
            System.out.println("-------------------------------------------");
            // 6.2构建单元格列表
            List<Cell> cells = result.listCells();
            for(Cell cell:cells){
                // 6.3 打印列簇名
                System.out.print(Bytes.toString(cell.getFamilyArray(),cell.getFamilyOffset(),cell.getFamilyLength()));
                //打印列名
                String columnName = Bytes.toString(cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength());
                System.out.print(":" + columnName);
//                System.out.print(":" + Bytes.toString(cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength()));
                //解决数值型乱码打印值
                //判断是否为数值型列
                if (columnName.equals("NUM_CURRENT") || columnName.equals("NUM_PREVIOUS")
                        || columnName.equals("NUM_USAGE") || columnName.equals("TOTAL_MONEY")) {
                    //打印数值型
                    System.out.println("=>" + Bytes.toDouble(cell.getValueArray(),cell.getValueOffset()));
                } else {
                    //打印字符串值
                    System.out.println("=>" + Bytes.toString(cell.getValueArray(),cell.getValueOffset(),cell.getValueLength()));
                }
                //打印值
//                System.out.println("=>" + Bytes.toString(cell.getValueArray(),cell.getValueOffset(),cell.getValueLength()));
            }
            System.out.println("-------------------------------------------");
        }
        //关闭资源
        resultScanner.close();
        table.close();
    }


}

在这里插入图片描述

3. 调用方法

在这里插入图片描述

4. 查看结果

在这里插入图片描述

5. 代码改进

在这里插入图片描述

改进后的结果
在这里插入图片描述

6. 解决数值型数据显示乱码的问题

打印显示字符串数据正常,但是如果hbase存储的是int、double、float等数值型数据时,显示就会乱码,解决的方法就是判断是否是数值型数据,如果是,则进行相应的转化。

(1) 代码改进

在这里插入图片描述

(2) 显示结果

在这里插入图片描述

乱码问题已经解决了

十、 案例七:Export Job导出数据

用法:

hbase org.apache.hadoop.hbase.mapreduce.Export 表名 路径

在这里插入图片描述
在这里插入图片描述
在webUI上查看结果

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐