HBase的javaAPI操作——DDL和DML

1、先定义Admin和Connection对象

  DDL操作需要Admin,DML操作需要Connection。

  因为client连接HMaster和HRegionserver都是通过zookeeper,所以只要连接zookeeper就可以访问两者。

    public static Connection connection;
    public static Admin admin;
    static{
        try {
            //1、获取配置
            Configuration conf = HBaseConfiguration.create();
            conf.set("hbase.zookeeper.quorum", "server001,server002,server003");
            //端口可以不配,默认就是2181
            conf.set("hbase.zookeeper.property.clientPort", "2181");
            //2、获取连接对象
            connection = ConnectionFactory.createConnection(conf);
            //3、获取Admin对象
            admin = connection.getAdmin();  //HBaseAdmin admin = new HBaseAdmin(conf);(已过时)
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

  再定义一个资源的关闭方法

private static void close(){
        //关闭Admin
        if (admin != null){
            try {
                admin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //关闭连接
        if (connection != null){
            try {
                connection.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

  这里注意一点,在执行时如果卡住或是报超时,在hosts配置zk的ip和主机名。

192.168.**.*** server001
192.168.**.*** server002
192.168.**.*** server003

2、DDL操作

  检查表是否存在、创建表、删除表、创建命名空间

    /**
     * 1、判断表是否存在
     */
    public static boolean isTableExist(String tableName) throws IOException {
        return admin.tableExists(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("该表已存在");
            return;
        }
        //3、创建表描述器
        HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
        //4、添加列族定义
        for (String cf : cfs) {
            //定义列族描述器
            HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cf);
            hTableDescriptor.addFamily(hColumnDescriptor);
        }
        //5、创建表
        admin.createTable(hTableDescriptor);
    }

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

    /**
     * 4、创建命名空间
     */
    public static void createNamespace(String namespace){
        //1、创建命名空间装饰器
        NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create(namespace).build();
        try {
            //2、创建命名空间
            admin.createNamespace(namespaceDescriptor);
        }
        //通过捕获异常来处理命名空间已存在
        catch (NamespaceExistException e){
            System.out.println(namespace+"命名空间已存在");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3、DML操作

   插入数据、查询数据-分为get和scan、删除数据(较为复杂)

    /**
     * 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));
        put.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn),Bytes.toBytes(value));
        //在同一个rowKey中插入多条数据可以再 put.addColumn(***);

        //3、插入数据,批量插入可以用 table.put(List<Put>)
        table.put(put);

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

    /**
     * 6、查询数据(get方式)
     */
    public static void queryDataByGet(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(2);

        //3、查询数据
        Result result = table.get(get);
        //4、解析result获取数据,一个rowKey对应多个Cell
        for (Cell cell : result.rawCells()) {
            //列族
            String family = Bytes.toString(CellUtil.cloneFamily(cell));
            //
            String column = Bytes.toString(CellUtil.cloneQualifier(cell));
            //
            String value = Bytes.toString(CellUtil.cloneValue(cell));
            //时间戳
            long time = cell.getTimestamp();
            System.out.println("列族:"+family+",列:"+column+",值:"+value+",时间:"+time);
        }
        //5、关闭表连接
        table.close();
    }

    /**
     * 7、查询数据(scan方式)
     */
    public static void queryDataByScan(String tableName) throws IOException {
        //1、获取表对象
        Table table = connection.getTable(TableName.valueOf(tableName));
        //2、创建Scan对象
        Scan scan = new Scan();
        //2.1、可以传入rowKey范围,左闭右开的
        //Scan scan = new Scan(Bytes.toBytes("1001"),Bytes.toBytes("1003"));
        //2.2、也可以传入Filter过滤器
        //3、扫描表
        ResultScanner resultScanner = table.getScanner(scan);
        //4、resultScanner分批获取数据
        for(Result result : resultScanner){
            //4、解析result获取数据,一个rowKey对应多个Cell
            for (Cell cell : result.rawCells()) {
                //列族
                String family = Bytes.toString(CellUtil.cloneFamily(cell));
                //
                String column = Bytes.toString(CellUtil.cloneQualifier(cell));
                //
                String value = Bytes.toString(CellUtil.cloneValue(cell));
                //时间戳
                long time = cell.getTimestamp();
                System.out.println("列族:"+family+",列:"+column+",值:"+value+",时间:"+time);
            }
        }
        //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对象(只传rowKey相当于命令行中的deleteall)
        Delete delete = new Delete(Bytes.toBytes(rowKey));
        //2.1、删除指定列的所有版本
        //delete.addColumns(Bytes.toBytes(cf),Bytes.toBytes(cn));
        //2.2、删除指定列的最新一个版本(其实是先获取最先版本数据,然后给该条数据加删除标记)
        //delete.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn));
        //2.3、带时间戳删除指定列的所有版本(小于等于指定时间戳的数据都会被删除)
        //delete.addColumns(Bytes.toBytes(cf),Bytes.toBytes(cn),System.currentTimeMillis());
        //2.4、删除指定版本的指定列(也就是时间戳相等的会被删除)
        //delete.addColumn(Bytes.toBytes(cf),Bytes.toBytes(cn),System.currentTimeMillis());
        //2.5、删除指定列族(删除多版本,这个也可以传时间戳,也是小于等于的关系)
        //delete.addFamily(Bytes.toBytes(cf));
        //3、删除数据
        table.delete(delete);
        //5、关闭表连接
        table.close();
    }

  其他的操作就不多说了,很好理解,这里说两个:

(1)scan方式获取数据

  new Scan()有三个构造方法

  

  获得结果 ResultScanner resultScanner = table.getSacnner(scan)。这里并不是返回一个 Result[] 数组,而是返回一个结果迭代器,分批返回查询结果(一般默认500条),因为HBase面向大数据,一次返回大量数据可能存在将内存打满的风险。

(2)删除数据delete(注意所谓删除只是添加一个删除标记)

  delete其实也是put,只不过put进去的是一个删除标记,查看源码可知最终走到相同的代码。这里结合命令行操作来分析

• 先看下命令行操作:

  

  命令行操作如果是多版本数据存储,会将所有版本数据都删除。这里再说下三种删除标记

    Delete:只对某一个版本生效(即只对指定时间戳生效,等于的关系),只在API中会出现

    DeleteColumn:对多个版本生效(小于等于的关系),作用于列

    DeleteFamily:对多个版本生效(小于等于的关系),作用于整个列族

• 再来看API操作

  

 

 

  

posted @ 2021-11-03 21:13  jingyi_up  阅读(278)  评论(0编辑  收藏  举报