zoukankan      html  css  js  c++  java
  • 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操作

      

      

  • 相关阅读:
    网络爬虫概述
    Redis常见问题汇总
    分布式锁和Redis事务
    Redis主从复制
    数据持久化
    位图操作bitmap
    数据类型:Hash散列数据类型
    进程池
    事件Event实现消费者模型
    事件Event
  • 原文地址:https://www.cnblogs.com/jing-yi/p/15505761.html
Copyright © 2011-2022 走看看