一、理论基础
Hbase基础见另一篇笔记《学习笔记 | HBase学习笔记》
本文示例完整源码地址:https://github.com/lysmile/spring-boot-demo/tree/master/spring-boot-hbase-demo
二、实战代码
2.1 依赖引入
<!--for hbase-->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>2.1.0-cdh6.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.1.0-cdh6.3.1</version>
</dependency>
2.2 配置项
hbase:
config:
hbase:
master: 192.168.1.11:600000
zookeeper:
property:
clientPort: 2181
quorum: 192.168.1.11,192.168.1.12,192.168.1.13
2.3 配置文件
2.3.1 配置文件读取
/**
* 从配置文件中读取hbase配置信息
* 配置文件格式:hbase.config.*=xxx
* @author smile
*/
@ConfigurationProperties(prefix = "hbase")
public class HbaseProperties {
private Map<String, String> config;
public Map<String, String> getConfig() {
return config;
}
public void setConfig(Map<String, String> config) {
this.config = config;
}
2.3.2 Hbase连接配置
@org.springframework.context.annotation.Configuration
@EnableConfigurationProperties(HbaseProperties.class)
public class HbaseConfig {
private final HbaseProperties prop;
public HbaseConfig(HbaseProperties properties) {
this.prop = properties;
}
@Bean
public Configuration configuration() {
Configuration configuration = HBaseConfiguration.create();
Map<String, String> config = prop.getConfig();
config.forEach(configuration::set);
return configuration;
}
@Bean
public Connection getConnection() throws IOException{
return ConnectionFactory.createConnection(configuration());
}
}
2.4 表的增、删、查
/**
* 创建表
* - 只有一个列族
* @param tableName 表名
* @param colFamily 列族
* @throws IOException
*/
public void createTable(String tableName, String colFamily) throws IOException {
TableName table = TableName.valueOf(tableName);
try (HBaseAdmin admin = (HBaseAdmin) connection.getAdmin()) {
if (admin.tableExists(table)) {
log.warn("表[{}]已存在!", tableName);
return;
}
ColumnFamilyDescriptor cfd = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(colFamily))
// 设置数据版本数量
.setMaxVersions(1)
// 设置副本数,默认是3
.setDFSReplication((short) 2)
.build();
TableDescriptor tableDes = TableDescriptorBuilder.newBuilder(table).setColumnFamily(cfd).build();
admin.createTable(tableDes);
}
}
/**
* 删除表
* @param tableName 表名称
*/
public void deleteTable(String tableName) throws IOException {
TableName tName = TableName.valueOf(tableName);
try (HBaseAdmin admin = (HBaseAdmin) connection.getAdmin()) {
if (admin.tableExists(tName)) {
admin.disableTable(tName);
admin.deleteTable(tName);
} else {
log.error("表 {} 不存在!", tableName);
return;
}
}
}
/**
* 列出hbase中所有的表
*/
public List<String> listTables() throws IOException {
List<String> tables = new ArrayList<>(8);
try (HBaseAdmin admin = (HBaseAdmin) connection.getAdmin()) {
TableName[] tableNames = admin.listTableNames();
for (TableName tableName : tableNames) {
tables.add(tableName.getNameAsString());
}
}
return tables;
}
2.5 根据Rowkey查询数据
/**
* 根据rowkey获取指定列数据
* @param tableName 表名
* @param rowkey rowkey
* @param colFamily 列族
* @param cols 列
* @return Result
*/
public Result getData(String tableName, String rowkey, String colFamily, List<String> cols) throws IOException, NotExistsException {
if (!tableExists(tableName)) {
throw new NotExistsException("表[" + tableName + "]不存在");
}
try(Table table = connection.getTable(TableName.valueOf(tableName))) {
Get get = new Get(Bytes.toBytes(rowkey));
if (null != cols) {
cols.forEach(col -> get.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(col)));
}
return table.get(get);
}
}
2.6 批量查询数据
2.6.1 查询参数定义
@Data
public class ScanParam {
private String tableName;
private String colFamily;
private List<String> columns;
private String startRow;
private String stopRow;
private int pageSize;
private Boolean reversed;
}
2.6.2 示例
/**
* 批量获取数据
* - 左闭右开
*/
public ResultScanner scanData(ScanParam param) throws IOException, NotExistsException {
log.debug("ScanBaseParam : {}", JSON.toJSON(param));
if (!tableExists(param.getTableName())) {
throw new NotExistsException(HbaseErrorEnum.TABLE_NOT_EXISTS.getMsg());
}
try (Table table = connection.getTable(TableName.valueOf(param.getTableName()))){
Scan scan = new Scan();
if (null != param.getReversed()) {
scan.setReversed(param.getReversed());
} else {
scan.setReversed(false);
}
if (null != param.getStartRow()) {
scan.withStartRow(Bytes.toBytes(param.getStartRow()));
}
if (null != param.getStopRow()) {
scan.withStopRow(Bytes.toBytes(param.getStopRow()));
}
if (null != param.getColumns()) {
for (String col : param.getColumns()) {
scan.addColumn(Bytes.toBytes(param.getColFamily()), Bytes.toBytes(col));
}
}
if (0 != param.getPageSize()) {
PageFilter pageFilter = new PageFilter(param.getPageSize());
scan.setFilter(pageFilter);
}
scan.setCaching(CACHING_SIZE);
return table.getScanner(scan);
}
}
2.7 插入数据
2.7.1 参数定义
@Data
public class DataVolume {
private String rowkey;
private Map<String, String> data;
}
2.7.2 示例
/**
* 插入单行数据
*/
public void put(String tableName, String colFamily, String rowkey, Map<String, String> data) throws NotExistsException, IOException{
if (!tableExists(tableName)) {
throw new NotExistsException(HbaseErrorEnum.TABLE_NOT_EXISTS.getMsg());
}
try (Table table = connection.getTable(TableName.valueOf(tableName))){
Put put = new Put(Bytes.toBytes(rowkey));
for (Map.Entry<String, String> entry : data.entrySet()) {
put.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(entry.getKey()), Bytes.toBytes(entry.getValue()));
}
table.put(put);
}
}
/**
* 批量插入
*/
public void batchPut(String tableName, String colFamily, List<DataVolume> dataVolumes) throws NotExistsException, IOException{
if (!tableExists(tableName)) {
throw new NotExistsException(HbaseErrorEnum.TABLE_NOT_EXISTS.getMsg());
}
try (Table table = connection.getTable(TableName.valueOf(tableName))){
List<Put> puts = new ArrayList<>();
for(DataVolume dataVolume : dataVolumes) {
Put put = new Put(Bytes.toBytes(dataVolume.getRowkey()));
for (Map.Entry<String, String> entry : dataVolume.getData().entrySet()) {
put.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(entry.getKey()), ObjectUtils.toByte(entry.getValue()));
}
puts.add(put);
}
table.put(puts);
}
}