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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!