hbaseAPI

java连接hbase

1.jdbc连接数据库6步

#1、注册驱动

//获取集群环境配置对象
configuration conf =HBaseConfiguration.create();
//配置zookeeper集群信息
conf.set("hbase.zookeeper.quorum", "master,node1,node2");

2、创建数据库连接对象

conn = ConnectionFactory.createConnection(conf);
System.out.println("hbase数据库连接对象:" + conn);

3、创建数据库操作对象

admin=this.conn.getAdmin()

4、对数据库进行操作
5、解析查询结果

6、关闭释放资源
admin.close();
conn.close();

2.Hbase api基础

1、如何创建一张表

建表至少指定表名和列簇名

  • create 'students','info'
//获取表名
TableName tn = TableName.valueOf("表名");
//判断表是否存在
boolean exists = admin.tableExists(tn);
if (!exists) {
  //创建表的描述器对象
  TableDescriptorBuilder tableDescriptorBuilder =   TableDescriptorBuilder.newBuilder(tn);
  //新版本创建列簇描述器并加入到表描述器中
  ColumnFamilyDescriptor e = ColumnFamilyDescriptorBuilder.of("e");
  ColumnFamilyDescriptor f = ColumnFamilyDescriptorBuilder.of("f");
  ArrayList<ColumnFamilyDescriptor> columnFamilyDescriptors = new ArrayList<>();
  columnFamilyDescriptors.add(e);
  columnFamilyDescriptors.add(f);
  //设置多个列簇
  tableDescriptorBuilder.setColumnFamilies(columnFamilyDescriptors);
  //设置一个列簇
//  tableDescriptorBuilder.setColumnFamily(e);

  admin.createTable(tableDescriptorBuilder.build());
}
else {
  System.out.println(Bytes.toString(tn.getName()) + "表已经存在!!");
}

2、如何删除一张表

先禁用 再删除

//先将表名封装成TableName对象
TableName tableName = TableName.valueOf("score");

//先判断是否存在
boolean b = admin.tableExists(tableName);
if (b) {
    admin.disableTable(tableName);

    admin.deleteTable(tableName);
} else {
    System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
}                                                                       

3、如何向hbase表中插入一列数据

1500100001,施笑槐,22,女,文科六班

  • put 'students','1500100001','info:name','施笑槐'

  • put 'students','1500100001','info:age','22'

  • put 'students','1500100001','info:gender','女'

  • put 'students','1500100001','info:clazz','文科六班'

  • 命令中的put: 代表一列

  • api中的Put:代表一行,可以设置多列


//先将表名封装成TableName对象
TableName tableName = TableName.valueOf("students");

//先判断是否存在
boolean b = admin.tableExists(tableName);
if (b) {
  //获取表对象
  Table students = conn.getTable(tableName);

  //将数据封装成Put对象
  //Put(byte [] row)
  Put put = new Put(Bytes.toBytes("1500101001"));

  //添加一列数据的方式1:
  //public Put addColumn(byte [] family, byte [] qualifier, byte [] value)
// put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes("李刚"));
//put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("age"),Bytes.toBytes("18"));
//put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("gender"),Bytes.toBytes("女"));
// put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("clazz"),Bytes.toBytes("文科一班"));

  //添加一列数据的方式2:将每一列封装成Cell对象
  //public Put add(Cell cell)
  //KeyValue是Cell接口的实现类
  //public KeyValue(final byte [] row, final byte [] family,final byte [] qualifier,   final byte [] value)
  put.add(new KeyValue(Bytes.toBytes("1500101001"), Bytes.toBytes("info"),     Bytes.toBytes("name"), Bytes.toBytes("李刚")));
  put.add(new KeyValue(Bytes.toBytes("1500101001"), Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("18")));
  put.add(new KeyValue(Bytes.toBytes("1500101001"), Bytes.toBytes("info"), Bytes.toBytes("gender"), Bytes.toBytes("女")));
  put.add(new KeyValue(Bytes.toBytes("1500101001"), Bytes.toBytes("info"), Bytes.toBytes("clazz"), Bytes.toBytes("文科一班")));

  //void put(Put put) 添加一行数据
  //void put(List<Put> puts) 添加多行数据
  students.put(put);
} else {
  System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
}

4、如何向hbase表中插入一批数据

//先将表名封装成TableName对象
TableName tableName = TableName.valueOf("score");

//先判断是否存在
boolean b = admin.tableExists(tableName);
if (b) {
  //获取表对象
  Table students = conn.getTable(tableName);
  //创建一个Put对象的List集合
  ArrayList<Put> putList = new ArrayList<>();

  //读取本地文件
  BufferedReader br = new BufferedReader(new FileReader("data/score.txt"));
  String line = null;
  Put put;
  while ((line = br.readLine()) != null) {
    String[] infos = line.split(",");
    put = new Put(Bytes.toBytes(infos[0]));
    //put.addColumn(Bytes.toBytes("a"), Bytes.toBytes("name"), Bytes.toBytes(infos[1]));
    //put.addColumn(Bytes.toBytes("b"), Bytes.toBytes("age"), Bytes.toBytes(infos[2]));
    //put.addColumn(Bytes.toBytes("c"), Bytes.toBytes("gender"), Bytes.toBytes(infos[3]));
    //put.addColumn(Bytes.toBytes("d"), Bytes.toBytes("clazz"), Bytes.toBytes(infos[4]));
    put.addColumn(Bytes.toBytes("e"), Bytes.toBytes("cid"), Bytes.toBytes(infos[1]));
    put.addColumn(Bytes.toBytes("f"), Bytes.toBytes("score"), Bytes.toBytes(infos[2]));

    //将put对象添加到集合中
    putList.add(put);
  }
  //void put(List<Put> puts) 添加多行数据
  students.put(putList);

  br.close();

} else {
  System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
}

5、如何获取一列数据

命令里get:获取一列或者一行
代码里的Get:获取一行

//先将表名封装成TableName对象
TableName tableName = TableName.valueOf("students");

//先判断是否存在
boolean b = admin.tableExists(tableName);
if (b) {
  //获取表对象
  Table students = conn.getTable(tableName);
  Get get = new Get(Bytes.toBytes("1500101001"));
  //Result get(Get get) 获取一行数据
  Result result = students.get(get); // 这里是根据行键获取的一行数据,若要得到每一列,就需要解析result
  //获取列的方式1:getValue(列簇, 列名)
  //String id = Bytes.toString(result.getRow()); // 获取行键,使用Bytes工具转字符串
  //String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
  //String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
  //String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
  //String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));

  //获取列的方式2:listCells() 列出一行中所有的单元格
  List<Cell> cells = result.listCells();
  String id = Bytes.toString(result.getRow());
  StringBuilder sb = new StringBuilder();
  sb.append("学号:").append(id).append(", ");
  for (Cell cell : cells) {
    //使用CellUtil工具类获取一个单元格中的内容
    // String id = Bytes.toString(CellUtil.cloneRow(cell)); //获取一个单元格中的行键
    String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
    String colValue = Bytes.toString(CellUtil.cloneValue(cell));
    //System.out.println("列名:" + colName + ", 列值:" + colValue);
    sb.append(colName).append(":").append(colValue).append(", ");
  }
  String str = sb.toString();
  str = str.substring(0, str.length() - 2);
  System.out.println(str);

  //TODO:自己实现传入多个Get获取多行数据
  //Result[] get(List<Get> gets) 获取多条数据

} else {
  System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
}

6、如何获取批量列数据

scan 'students'

//先将表名封装成TableName对象
TableName tableName = TableName.valueOf("students");

//先判断是否存在
boolean b = admin.tableExists(tableName);
if (b) {
  //获取表对象
  Table students = conn.getTable(tableName);

  Scan scan = new Scan(); //若使用无参构造方法创建Scan对象,表示全表扫描
  //老版本写法
  //scan.setStartRow(Bytes.toBytes("1500100837")); //设置开始行键
  //scan.withStartRow(Bytes.toBytes("1500100837"));
  //scan.withStopRow(Bytes.toBytes("1500100848")); //设置结束行键

  scan.setLimit(10); //取前几条


  //ResultScanner getScanner(Scan scan)
  ResultScanner rs = students.getScanner(scan); // rs中存储了多行数据
  Iterator<Result> resultIterator = rs.iterator(); //获取所有行数据组成的迭代器
  while (resultIterator.hasNext()) { //判断下一行是否有数据
    Result result = resultIterator.next(); //获取一行数据
    //获取列的方式1:getValue(列簇, 列名)
    //String id = Bytes.toString(result.getRow()); // 获取行键,使用Bytes工具转字符串
    //String name = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name")));
    //String age = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age")));
    //String gender = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("gender")));
    //String clazz = Bytes.toString(result.getValue(Bytes.toBytes("info"), Bytes.toBytes("clazz")));
    //System.out.println("学号:" + id + ", 姓名:" + name + ", 年龄:" + age + ", 性别:" + gender + ", 班级" + clazz);

    //获取列的方式2:listCells() 列出一行中所有的单元格
    List<Cell> cells = result.listCells();
    String id = Bytes.toString(result.getRow());
    StringBuilder sb = new StringBuilder();
    sb.append("学号:").append(id).append(", ");
    for (Cell cell : cells) {
      //使用CellUtil工具类获取一个单元格中的内容
      //String id = Bytes.toString(CellUtil.cloneRow(cell)); //获取一个单元格中的行键
      String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
      String colValue = Bytes.toString(CellUtil.cloneValue(cell));
      //System.out.println("列名:" + colName + ", 列值:" + colValue);
      sb.append(colName).append(":").append(colValue).append(", ");
    }
    String str = sb.toString();
    str = str.substring(0, str.length() - 2);
    System.out.println(str);
  }
} else {
  System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
}

7、如何创建预分region表

因为hbase将来可能会发生热点数据的问题,某一个RegionServer接收的处理请求太多了,与其它的RegionServer工作量产生明显的区别

  • 就会导致该RegionServer挂掉,我们可以采取将部分请求分散到其它的RegionServer上进行处理

分散的依据:

  • 1、hbase表中的数据,行键是根据字典顺序排序的,这就决定了我们添加数据的时候,根据行键的顺序,找到对应的region做添加

  • 2、若我们将一张表根据行键切分出多个region,由hmaster自动会对多个region进行负载均衡,重新分配

  • 3、结合第一点,将来我们的请求就会根据行键被分散到其它的regionserver上了

  • e h l o t

//先将表名封装成TableName对象
TableName tableName = TableName.valueOf("split_t");

//创建表描述器对象
TableDescriptorBuilder splitT = TableDescriptorBuilder.newBuilder(tableName);

//创建列簇描述器对象
//HColumnDescriptor info = new HColumnDescriptor("info");
ColumnFamilyDescriptor info = ColumnFamilyDescriptorBuilder.of("info");

//将列簇加入到表中
splitT.setColumnFamily(info);

//e  h  l   o  t
byte[][] splits = {
Bytes.toBytes("e"),
Bytes.toBytes("h"),
Bytes.toBytes("l"),
Bytes.toBytes("o"),
Bytes.toBytes("t")
};


//创建普通hbase表
//admin.createTable(splitT.build()); // 默认一开始只会提供一个region,只会被一个regionserver所管理
//创建预分region表
//createTable(TableDescriptor desc, byte[][] splitKeys)
admin.createTable(splitT.build(), splits); // 切分出的region由master负载均衡,会有多个regionserver所管理

3.写一个habse工具类

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
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.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

public class HbaseTool {
    public static final Connection CONNECTION;

    public static final Admin ADMIN;

    private HbaseTool() {
    }

    static {
        Connection tmpConn = null;
        Admin tmpAdmin = null;
        try {
            //读取配置文件,获取zookeeper信息
            Properties properties = new Properties();
            properties.load(new BufferedReader(new FileReader("src/main/resources/infos.properties")));

            String zkInfo = properties.getProperty("hbase.zookeeper.quorum");

            Configuration conf = HBaseConfiguration.create();
            //配置zookeeper集群信息
            conf.set("hbase.zookeeper.quorum", zkInfo);

            //获取数据库连接对象
            tmpConn = ConnectionFactory.createConnection(conf);

            //获取数据库操作对象
            tmpAdmin = tmpConn.getAdmin();
        } catch (Exception e) {
            e.printStackTrace();
        }
        CONNECTION = tmpConn;
        ADMIN = tmpAdmin;
    }

    public static Table getOneTable(String tableName) {
        Table t = null;
        try {
            //先将表名封装成TableName对象
            TableName tn = TableName.valueOf(tableName);

            //先判断是否存在
            boolean b = ADMIN.tableExists(tn);
            if (b) {
                //获取表对象
                t = CONNECTION.getTable(tn);
            } else {
                System.out.println(Bytes.toString(tn.getName()) + "表不存在!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return t;
    }

    //创建hbase表
    public static void createHbaseTable(String tableName, String... cfs) {
        try {
            TableName tn = TableName.valueOf(tableName);
            //应该在创建表之前先判断表是否存在
            boolean b = ADMIN.tableExists(tn);
            if (!b) {
                TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tn);

                //创建一个存储列簇描述器的集合
                ArrayList<ColumnFamilyDescriptor> cfList = new ArrayList<>();

                for (String cf : cfs) {
                    //新版本创建列簇描述器并加入到表描述器中的做法
                    ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.of(cf);
                    cfList.add(cfd);
                }

                tableDescriptorBuilder.setColumnFamilies(cfList);

                //void createTable(TableDescriptor desc)
                ADMIN.createTable(tableDescriptorBuilder.build());
                System.out.println(Bytes.toString(tn.getName()) + " 表创建成功!");
            } else {
                System.out.println(Bytes.toString(tn.getName()) + "表已经存在!!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //删除表
    public static void deleteTable(String tName) {
        try {
            //先将表名封装成TableName对象
            TableName tableName = TableName.valueOf(tName);
            //先判断是否存在
            boolean b = ADMIN.tableExists(tableName);
            if (b) {
                ADMIN.disableTable(tableName);
                ADMIN.deleteTable(tableName);
            } else {
                System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //查询一批数据
    public static Iterator<Result> scanData(String tn) {
        Iterator<Result> resultIterator = null;
        try {
            //先将表名封装成TableName对象
            TableName tableName = TableName.valueOf(tn);

            //先判断是否存在
            boolean b = ADMIN.tableExists(tableName);
            if (b) {
                //获取表对象
                Table students = CONNECTION.getTable(tableName);

                Scan scan = new Scan(); //若使用无参构造方法创建Scan对象,表示全表扫描
                //ResultScanner getScanner(Scan scan)
                ResultScanner rs = students.getScanner(scan); // rs中存储了多行数据
                resultIterator = rs.iterator(); //获取所有行数据组成的迭代器

            } else {
                System.out.println(Bytes.toString(tableName.getName()) + "表不存在!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return resultIterator;
    }


    //TODO:自己编写
//    public static Iterator<Result> scanData(String tableName, int limit){
//
//    }

    //创建预分region表 "test3", "cf1","cf2","f","m"
    public static void createPreviewTable(String tn, List<String> cfs, List<String> splitRowKeys) {
        try {
            //先将表名封装成TableName对象
            TableName tableName = TableName.valueOf(tn);

            //创建表描述器对象
            TableDescriptorBuilder tdb = TableDescriptorBuilder.newBuilder(tableName);

            //创建列簇描述器对象
            //创建一个存储列簇描述器的集合
            ArrayList<ColumnFamilyDescriptor> cfList = new ArrayList<>();
            for (String cf : cfs) {
                //新版本创建列簇描述器并加入到表描述器中的做法
                ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.of(cf);
                cfList.add(cfd);
            }
            //将列簇加入到表中
            tdb.setColumnFamilies(cfList);

            List<byte[]> splitList = splitRowKeys
                    .stream()
                    .map(Bytes::toBytes).collect(Collectors.toList()); // List<"f","m">

            byte[][] splitKeys = new byte[splitList.size()][];

            for (int i = 0; i < splitList.size(); i++) {
                splitKeys[i] = splitList.get(i);
            }

            //创建预分region表
            //createTable(TableDescriptor desc, byte[][] splitKeys)
            ADMIN.createTable(tdb.build(), splitKeys); // 切分出的region由master负载均衡,会有多个regionserver所管理

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


    //遍历Result结果的方法
    public static void printResult(Result result) {
        // 获取一行所有的列单元格
        List<Cell> cells = result.listCells();
        //获取行键
        String rowKey = Bytes.toString(result.getRow());
        StringBuilder sb = new StringBuilder();
        sb.append("行键:").append(rowKey).append(", ");
        for (Cell cell : cells) {
            String colName = Bytes.toString(CellUtil.cloneQualifier(cell));
            String colValue = Bytes.toString(CellUtil.cloneValue(cell));
            sb.append(colName).append(":").append(colValue).append(", ");
        }
        String str = sb.toString();
        str = str.substring(0, str.length() - 2);
        System.out.println(str);
    }

    public static void close() {
        if (ADMIN != null) {
            try {
                ADMIN.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (CONNECTION != null) {
            try {
                CONNECTION.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

再写一个properties文件,存储zookeeper信息

hbase.zookeeper.quorum=master,node1,node2
posted @   rrrzzzrrr  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示