最近项目使用到hbase当做数据库存储数据,经过多番网上搜索并把通用方法进行整合,对hbase操作的功能写成了自己的通用方法,现在公布出来希望对大家有所帮助,后期有新的通用功能会实时更新的,通用方法不采用springboot集成的hbase,使用原生java API 操作hbase方法
开发环境
系统:windows
JDK:1.8
开发工具:Intellij IDEA
虚拟机:vmware
三台linux节点: 172.162.15.111、172.162.15.112、172.162.15.113
Linux:CentOS 7 迷你版 CentOS-7-x86_64-Minimal-1708.iso
Hadoop: Hadoop-3.1.2
Hbase : hbase-2.0.5
Zookeeper: zookeeper-3.4.1
第二步:配置windows系统host,根据您的需求,这一步可有可无
#虚拟机访问地址
172.162.15.111 davidone
172.162.15.112 davidtwo
172.162.15.113 davidthree
第三步:项目结构配置pom.xml
org.springframework.boot
spring-boot-configuration-processor
true
org.apache.hbase
hbase-client
2.0.5
org.slf4j
slf4j-log4j12
log4j
log4j
javax.servlet
servlet-api
application.yml 这个配置以增量的方式添加到文件
logging:
config: classpath:Logback.xml
bigdata:
config:
hBaseConfigMap: {hbase.zookeeper.quorum : 'davidone:2181,davidtwo:2181,davidthree:2181'}
第四步:核心代码
@Component()
@ConfigurationProperties(prefix = "bigdata.config")
public class BigDataConfig {
private Map hBaseConfigMap;
public Map gethBaseConfigMap() {
return hBaseConfigMap;
}
public void sethBaseConfigMap(Map hBaseConfigMap) {
this.hBaseConfigMap = hBaseConfigMap;
}
}
HBaseRepository.java 通用操作hbase数据代码,包含了通用的二级搜索,分页,多条件查询,要求对hbase shell 操作有一定的了解后,能够很好的了解这个通用方法
建议去看下这位博主写的文章:HBase学习笔记
分段进行对HBaseRepository进行展示
4.1、对hbase进行初始化
@Autowired
private BigDataConfig bigDataConfig;
private static Configuration configuration = HBaseConfiguration.create();
//设置连接池
private static ExecutorService executorServicePoolSize = Executors.newScheduledThreadPool(20);
private ThreadLocal connectionThreadLocal = new ThreadLocal<>();
private ThreadLocal adminThreadLocal = new ThreadLocal<>();
private static Connection connection = null;
private static Admin admin = null;
private final byte[] POSTFIX = new byte[] { 0x00 };
/**
* 加载HBase配置信息
*/
private void initConfigurationInfo(){
Map hBaseConfigMap = bigDataConfig.gethBaseConfigMap();
if(hBaseConfigMap.size() == 0){
logger.debug(MessageFormat.format("HBase配置信息初始化失败:{0}",JSON.toJSONString(hBaseConfigMap)));
}else{
for (Map.Entry confEntry : hBaseConfigMap.entrySet()) {
configuration.set(confEntry.getKey(), confEntry.getValue());
}
}
}
/**
* 初始化HBase client admin
*
*/
private void initHBaseClientAdmin(){
try{
admin = adminThreadLocal.get();
if(admin == null && connection != null){
admin = connection.getAdmin();
adminThreadLocal.set(admin);
}else{
logger.debug(MessageFormat.format("创建hBase connection连接 失败:{0}",connection));
}
}catch (Exception e){
logger.error(MessageFormat.format("初始化hBase client admin 客户端管理失败:错误信息:{0}",e));
}
}
/**
* 初始化HBase资源
*/
public void initRepository(){
try{
initConfigurationInfo();
connection = connectionThreadLocal.get();
if(connection == null){
connection = ConnectionFactory.createConnection(configuration, executorServicePoolSize);
connectionThreadLocal.set(connection);
}
initHBaseClientAdmin();
}catch (Exception e){
logger.error(MessageFormat.format("创建hBase connection 连接失败:{0}",e));
e.printStackTrace();
}finally {
close(admin,null,null);
}
}
4.2、提取使用到的通用方法
/**
* 通用方法 -> 获取table 用于添加和删除
* @param tableName 表名
* @return Table
*/
private Table getTable(String tableName) {
try {
return connection.getTable(TableName.valueOf(tableName));
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 通用方法-> 创建表
* @param tableName 表名
* @param columnFamily 列族集合
* @return
* @throws Exception
*/
private int createTable(String tableName,List columnFamily) throws Exception {
if(admin.tableExists(TableName.valueOf(tableName))){
logger.debug(MessageFormat.format("创建HBase表名:{0} 在HBase数据库中已经存在",tableName));
return 2;
}else{
List familyDescriptors =new ArrayList<>(columnFamily.size());
for(String column : columnFamily){
familyDescriptors.add(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(column)).build());
}
TableDescriptor tableDescriptor = TableDescriptorBuilder.newBuilder(TableName.valueOf(tableName))
.setColumnFamilies(familyDescriptors).build();
admin.createTable(tableDescriptor);
logger.info(MessageFormat.format("创建表成功:表名:{0},列簇:{1}",tableName,JSON.toJSONString(columnFamily)));
return 1;
}
}
/**
* 通用方法 -> 处理分页数据
* @param scan 过滤的数据
* @param pageSize 每页显示的数量
* @param lastRowKey 当前页的最后一行(rowKey)
* @return
*/
private FilterList handlePageFilterData(Scan scan, int pageSize,String lastRowKey){
Filter pageFilter = new PageFilter(pageSize);
FilterList pageFilterList = new FilterList();
pageFilterList.addFilter(pageFilter);
if(!StringUtils.isEmpty(lastRowKey)){
byte[] startRow = Bytes.add(Bytes.toBytes(lastRowKey), POSTFIX);
scan.setStartRow(startRow);
}
return pageFilterList;
}
/**
* 通用方法 -> 处理查询条件
* @param columnFamily 列簇
* @param queryParam 过滤列集合 ("topicFileId,6282")=>("列,值")
* @param regex 分隔字符
* @param bool 查询方式:and 或 or | true : and ;false:or
* @return
*/
private FilterList queryFilterData(String columnFamily,List queryParam,String regex,boolean bool){
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
if(!bool){
filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE);
}
for(String param: queryParam){
String[] queryArray = param.split(regex);
SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(Bytes.toBytes(columnFamily), Bytes.toBytes(queryArray[0]), CompareOperator.EQUAL,Bytes.toBytes(queryArray[1]));
singleColumnValueFilter.setFilterIfMissing(true);
filterList.addFilter(singleColumnValueFilter);
}
return filterList;
}
/**
* 通用方法 -> 根据条件查询
* @param table 表名
* @param scan 过滤条件
* @return
*/
private List> queryData(Table table,Scan scan){
ResultScanner resultScanner =null;
List> resultList = new ArrayList<>();
try {
resultScanner = table.getScanner(scan);
for(Result result : resultScanner){
logger.info(MessageFormat.format("查询每条HBase数据的行号:{0}",Bytes.toString(result.getRow())));
Map resultMap = new HashMap<>();
resultMap.put("rowKey",Bytes.toString(result.getRow()));
for(Cell cell :result.listCells()){
resultMap.put(Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()),
Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength())
);
}
resultList.add(resultMap);
}
logger.info(MessageFormat.format("查询指定表中数据信息:表名:{0},查询结果:{1}",Bytes.toString(table.getName().getName()),JSON.toJSONString(resultList)));
} catch (Exception e) {
e.printStackTrace();
logger.debug(MessageFormat.format("查询指定表中数据信息:表名:{0},错误信息:{1}",Bytes.toString(table.getName().getName()),e.getMessage()));
}finally {
close(null,resultScanner,table);
}
return resultList;
}
/**
* 通用方法 -> 统计
* @param table
* @param scan
* @return
*/
private int queryDataCount(Table table,Scan scan){
scan.setFilter(new FirstKeyOnlyFilter());
ResultScanner resultScanner = null;
int rowCount = 0;
try {
resultScanner = table.getScanner(scan);
for(Result result : resultScanner){
rowCount += result.size();
}
logger.info(MessageFormat.format("统计全表数据总数:表名:{0},查询结果:{1}",Bytes.toString(table.getName().getName()),rowCount));
return rowCount;
} catch (Exception e) {
e.printStackTrace();
logger.debug(MessageFormat.format("查询指定表中数据信息:表名:{0},错误信息:{1}",Bytes.toString(table.getName().getName()),e.getMessage()));
return rowCount;
}finally {
close(null,resultScanner,table);
}
}
/**
* 通用方法 ->关闭流
*/
private void close(Admin admin, ResultScanner rs, Table table){
if(admin != null){
try {
admin.close();
} catch (IOException e) {
logger.error("关闭Admin失败",e);
}
}
if(rs != null){
rs.close();
}
if(table != null){
try {
table.close();
} catch (IOException e) {
logger.error("关闭Table失败",e);
}
}
}
4.3、根据个人需求可以同时创建单张或多张数据表
/**
* 同时创建多张数据表
* @param tableMap 数据表 map
* @return
*/
public boolean createManyTable(Map> tableMap){
try{
if(admin != null){
for (Map.Entry> confEntry : tableMap.entrySet()) {
createTable(confEntry.getKey(), confEntry.getValue());
}
}
}catch (Exception e){
logger.error(MessageFormat.format("创建多个表出现未知错误:{0}",e.getMessage()));
e.printStackTrace();
return false;
}finally {
close(admin,null,null);
}
return true;
}
/**
* 创建hbase表和列簇
* @param tableName 表名
* @param columnFamily 列簇
* @return 1:创建成功;0:创建出错;2:创建的表存在
*/
public int createOneTable (String tableName,String... columnFamily){
try{
//创建表,先查看表是否存在,然后在删除重新创建
if(admin != null){
return createTable(tableName,Arrays.asList(columnFamily));
}else{
logger.error("admin变量没有初始化成功");
return 0;
}
}catch (Exception e){
logger.debug(MessageFormat.format("创建表失败:{0},错误信息是:{1}",tableName,e.getMessage()));
e.printStackTrace();
return 0;
}finally {
close(admin,null,null);
}
}
4.4、同时添加或更新多列和单列
/**
* 插入or 更新记录(单行单列族-多列多值)
* @param tableName 表名
* @param row 行号 唯一
* @param columnFamily 列簇名称
* @param columns 多个列
* @param values 对应多个列的值
*/
public boolean insertManyColumnRecords(String tableName,String row,String c