ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Hbase——JavaAPI操作笔记

2020-11-19 18:33:55  阅读:261  来源: 互联网

标签:String tableName JavaAPI Bytes 笔记 toBytes new Hbase table


写在前面

这篇文章上接Hbase搭建和Shell命令,咕咕咕了好久,最近终于有空歇下来总结一下了。

基本API——增删改

导入依赖

首先新建一个maven项目,导入如下的依赖:

<dependencies>    
<dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-server</artifactId>
        <version>1.3.1</version>
    </dependency>

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

这里的版本要和服务器里的版本相对应。

准备工作

为了方便以后的连接,我们直接把连接HBase的配置写到静态代码块里,这样每次这个类运行的时候都会执行这些代码:

    private static Connection connection = null;
    private static Admin admin = null;
    static {
        try {
            // 1.获取配置信息
            Configuration configuration = HBaseConfiguration.create();
            configuration.set("hbase.zookeeper.quorum","hadoop03,hadoop04,hadoop05");

            // 2.创建连接对象
            connection = ConnectionFactory.createConnection(configuration);

            // 3.创建admin对象
            admin = connection.getAdmin();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这里的configuration里set的值要换成你自己的hbase地址。我这里是在windows里配置了hosts文件映射,所以可以直接写主机名。建议都去配一下映射,不然好像会报错。

检验表是否存在

先来看代码:

    /**
     * 1.判断表是否存在
     * @return
     */
    public static boolean isTableExist(String tableName) throws IOException {
        // 1.判断表是否存在
        boolean exists = admin.tableExists(TableName.valueOf(tableName));
        // 2.关闭连接
        admin.close();
        // 3.返回结果
        return exists;
    }

这里要注意的点是,tableExists()方法只能传入一个TableName对象,我们可以通过TableName.valueOf()来获得一个TableName对象。

创建表

/**
 * 2. 创建表
 */
public static void createTable(String tableName,String... cfs) throws IOException {
    // 1.判断是否存在列族信息
    if(cfs.length <=0){
        System.out.println("请设置列族信息!");
        return;
    }
    // 2.判断表是否存在
    if(isTableExist(tableName)){
        System.out.println(tableName + "表已存在!");

        return;
    }
    // 3.创建表描述器
    HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
    // 4.循环添加列族信息
    for (String cf : cfs) {
        // 5.创建列族描述器
        HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cf);
        // 6.添加具体的列族信息
        hTableDescriptor.addFamily(hColumnDescriptor);

    }
    // 7.创建表
    admin.createTable(hTableDescriptor);
}

这里要注意的点是,我们通过面向对象的思想来创建一个表,首先创建一个表描述器,然后对表描述器添加列族描述器。这里只是一个例子,可以传入的类型不止这些,可以再细看API。

删除表

删除表,就跟我们用shell操作一样,先让表失效,再去删除表:

    /**
     * 3.删除表
     */
    public static void dropTable(String tableName) throws IOException {
        // 1.判断表是否存在
        if(!isTableExist(tableName)){
            System.out.println(tableName + "表不存在!!");
            return;
        }
        // 2.使表下线
        admin.disableTable(TableName.valueOf(tableName));

        // 3.删除表
        admin.deleteTable(TableName.valueOf(tableName));
    }

向表插入(修改)数据

向表插入或者修改数据,我们使用Put对象即可。创建一个Put对象,然后对其赋值即可:

    /**
     * 5.向表插入数据
     */
    public static void putData(String tableName,String rowKey,String cf,String cn,String value) throws IOException {
        // 1.获取表对象
        Table table = connection.getTable(TableName.valueOf(tableName));
        // 2.创建put对象
        Put put = new Put(Bytes.toBytes(rowKey));
        // 3.给Put对象赋值
        put.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn),Bytes.toBytes(value));
        // 4.插入数据
        table.put(put);
        // 5.关闭表连接
        table.close();
    }

删除表中数据

/**
     * 8.删除数据
     */
    public static void deleteData(String tableName,String rowKey,String cf,String cn) throws IOException {
        // 1.获取表对象
        Table table = connection.getTable(TableName.valueOf(tableName));
        // 2.构建删除对象
        Delete delete = new Delete(Bytes.toBytes(rowKey));

        // 2.1设置删除的列
//        delete.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn));
//        delete.addColumns(Bytes.toBytes(cf),Bytes.toBytes(cn));
        // 2.2 删除指定的列族
        delete.addFamily(Bytes.toBytes(cf));
        // 3.执行删除操作
        table.delete(delete);

        // 4.关闭连接
        table.close();
    }

这里我们在删除时,可以指定删除的列或者列族,进而达到指定的列或者列族的目的。

查询API——get和scan

get

/**
 * 6.获取数据 (get)
 */
public static void getData(String tableName,String rowKey,String cf,String cn) throws IOException {
    // 1.获取表对象
    Table table = connection.getTable(TableName.valueOf(tableName));
    // 2.创建get对象
    Get get = new Get(Bytes.toBytes(rowKey));
    // 2.1指定获取的列族
    get.addFamily(Bytes.toBytes(cf));
    // 2.2指定列族和列
    get.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn));
    // 2.3设置获取数据的版本数
    get.setMaxVersions();
    // 3.获取数据
    Result result = table.get(get);
    // 4.解析result并打印
    for (Cell cell : result.rawCells()) {
        // 5.打印数据
        System.out.println("cf:" + Bytes.toString(CellUtil.cloneFamily(cell)) +
                ",CN:" + Bytes.toString(CellUtil.cloneQualifier(cell)) +
                ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
    }
    // 6.关闭表连接
    table.close();
}

get查询方法和scan查询方法的区别在于,get查询方法获得指定的值,而scan方法获得某一范围内的值。

scan

/**
 * 7.获取数据(scan)
 */
public static void scanTable(String tableName) throws IOException {
    // 1.获取表对象
    Table table = connection.getTable(TableName.valueOf(tableName));

    // 2.构建Scan对象 左闭右开
    Scan scan = new Scan(Bytes.toBytes("1001"),Bytes.toBytes("1003"));
    // 3.扫描表
    ResultScanner scanner = table.getScanner(scan);
    // 4.解析scanner
    for (Result result : scanner) {
        // 5.解析Result并打印
        for (Cell cell : result.rawCells()) {
            // 6.打印数据
            System.out.println("RoleKey:" + Bytes.toString(CellUtil.cloneRow(cell))+
                    ",cf:" + Bytes.toString(CellUtil.cloneFamily(cell)) +
                    ",CN:" + Bytes.toString(CellUtil.cloneQualifier(cell)) +
                    ",Value:" + Bytes.toString(CellUtil.cloneValue(cell)));
        }
    }
    // 7.关闭连接
    table.close();

}

进阶查询——过滤器和比较器

这里我通过一个案例来举例:

假设现在有这样一个需求:根据用户输入的对应字段来做一个多条件查询,例如目前要查询的字段有jgmc(机构名称),szdy(所在地域),jsxqmc(技术需求名称)。假设已经把数据存入Hbase(一个列族名为dcwjxx,字段名为对应列),如何使用Hbase实现该查询?

案例中的需求十分明确,我们要根据用户输入的各个字段来拼接查询条件。这种事用mysql十分容易实现,那么用hbase呢?还是先来看代码:

    public List<Dcwjxx> searchByCondition(String jgmc, String szdy,String jsxqmc) {
        // 根据条件是不是空来封装过滤器
        Scan scan = new Scan();
        // 按或条件查询
        FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE);
        if (!TextUtils.isEmpty(jgmc)) {
            SubstringComparator jgmcSubstringComparator = new SubstringComparator(jgmc);
            SingleColumnValueFilter jgmcFilter = new SingleColumnValueFilter(Bytes.toBytes("dcwjxx"),Bytes.toBytes(
                    "jgmc"), CompareFilter.CompareOp.EQUAL,jgmcSubstringComparator);
            filterList.addFilter(jgmcFilter);
        }
        if (!TextUtils.isEmpty(szdy)) {
            SubstringComparator szdySubstringCom = new SubstringComparator(szdy);
            SingleColumnValueFilter szdyFilter = new SingleColumnValueFilter(Bytes.toBytes("dcwjxx"),Bytes.toBytes(
                    "szdy"), CompareFilter.CompareOp.EQUAL,szdySubstringCom);
            filterList.addFilter(szdyFilter);
        }
        if (!TextUtils.isEmpty(jsxqmc)) {
            SubstringComparator jsxqmcSubstringCom = new SubstringComparator(jsxqmc);
            SingleColumnValueFilter jsxqmcFilter = new SingleColumnValueFilter(Bytes.toBytes("dcwjxx"),Bytes.toBytes(
                    "jsxqmc"), CompareFilter.CompareOp.EQUAL,jsxqmcSubstringCom);
            filterList.addFilter(jsxqmcFilter);
        }
        scan.setFilter(filterList);
        return (List<Dcwjxx>) getResult(scan);
    }

这里的getResult方法把返回的结果封装成了我们需要的对象,不需要在意这个方法,我们来看看如何用HBase的API拼接条件查询。

  • 首先我们要明确,我们这是一个多条件的过滤,且是或的关系。
  • 我们先定义一个FilterList对象,这个对象可以存储多个过滤器,这样我们就可以存储多个过滤条件了。这里传入一个或运算符
  • 之后,根据条件是否为空来拼接filter,这里我们使用了SubstringComparator比较器,这是Hbase自带的比较器中的一种,其作用在类名上写的十分明确了,即判断传入的字符串是不是要查询的字符串的子串。
  • 然后我们定义一个SingleColumnValueFilter过滤器,代表我们要对一个单元格数据进行处理,传入列族,列名和比较器运算符以及比较器,最后添加到filterList即可。
  • 这样一来,我们就实现了类似mysql中的where语句的查询了。

总结

总的来说,Hbase作为一个非关系型分布式数据库和mysql这类关系型数据库差别还是比较大的,操作起来也有诸多不适应。还是希望能多多理解。

标签:String,tableName,JavaAPI,Bytes,笔记,toBytes,new,Hbase,table
来源: https://www.cnblogs.com/wushenjiang/p/14007221.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有