一、配置
1、HBase版本
2.5.6
2、springboot依赖
<!-- jpa 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.7.4</version>
</dependency>
<!-- lombok 依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.5.6</version> <!-- 替换为你使用的 HBase 版本 -->
</dependency>
3、yml配置
spring:
datasource:
mysql-main:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://XXXXXX:3306/metadate?useUnicode=true&characterEncoding=utf-8
username: root
password: XXXXXX
请根据自身需要替换XXXXXX
4、HBase配置类Config
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
@org.springframework.context.annotation.Configuration
public class HBaseConfig {
@Bean
public Connection hbaseConnection() throws Exception {
Configuration config = HBaseConfiguration.create();
// 配置 HBase 连接信息,例如 ZooKeeper 地址等
config.set("hbase.zookeeper.quorum", "node1");
return ConnectionFactory.createConnection(config);
}
}
二、实体类
1、实体类
(1)namespace
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "namespace")
public class HbaseNamespaceEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="namespace",unique = true)
private String namespace;
@Column(name="owner")
private String owner;
}
(2) table
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "hbasetable")
public class HbaseTableEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="name")
private String name;
@Column(name="owner")
private String owner;
@Column(name="nid")
private Long nid;
}
(3) columnfamilies
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "columnfamilies")
public class HbaseColumnfamiliesEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="family")
private String family;
@Column(name="tid")
private Long tid;
}
(4)column
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "hbasecolumn")
public class HbaseColumnEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="id")
private Long id;
@Column(name="rowkey")
private String rowkey;
@Column(name="name")
private String name;
@Column(name="fid")
private Long fid;
}
2、 Repository接口
(1)namespace
import com.example.hivestart.entity.Hbase.HbaseNamespaceEntity;
import com.example.hivestart.entity.Hbase.HbaseTableEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface HbaseNamespaceEntityRepository extends JpaRepository<HbaseNamespaceEntity,Integer> {
HbaseNamespaceEntity findByNamespace(String namespace);
}
(2)table
import com.example.hivestart.entity.Hbase.HbaseTableEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface HbaseTableEntityRepository extends JpaRepository<HbaseTableEntity,Integer> {
HbaseTableEntity findByName(String name);
boolean deleteById(long id);
}
(3)columnfamilies
import com.example.hivestart.entity.Hbase.HbaseColumnfamiliesEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface HbaseColumnfamiliesEntityRepository extends JpaRepository<HbaseColumnfamiliesEntity,Integer> {
HbaseColumnfamiliesEntity findByFamily(String family);
List<HbaseColumnfamiliesEntity> findByTid(long tid);
boolean deleteById(long id);
}
(4)column
import com.example.hivestart.entity.Hbase.HbaseColumnEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface HbaseColumnEntityRepository extends JpaRepository<HbaseColumnEntity,Integer> {
HbaseColumnEntity findByNameAndFidAndRowkey(String name,long fid,String rowkey);
boolean deleteById(long id);
List<HbaseColumnEntity> findByFid(long familiyId);
}
三、操作
1、Namespace
(1)创建
//创建命名空间
@PostMapping("/createNamespace")
public String createNamespace(@RequestParam String namespace) throws IOException {
//TODO:需要登录获取用户
String owner="root";
boolean serviceNamespace = hbaseService.createNamespace(namespace,owner);
if (serviceNamespace){
HbaseNamespaceEntity namespaceEntity=new HbaseNamespaceEntity();
namespaceEntity.setNamespace(namespace);
namespaceEntity.setOwner(owner);
namespaceEntityRepository.save(namespaceEntity);
return "创建成功";
}else {
return "创建失败";
}
}
Service方法
/**
* 创建命名空间
*
* @param namespace 命名空间名称
*/
public boolean createNamespace(String namespace,String owner) throws IOException {
// 1. 获取 admin
// 此处的异常先不要抛出 等待方法写完 再统一进行处理
// admin 的连接是轻量级的 不是线程安全的 不推荐池化或者缓存这个连接
Admin admin = hbaseConnection.getAdmin();
// 2. 调用方法创建命名空间
// 代码相对 shell 更加底层 所以 shell 能够实现的功能 代码一定能实现
// 所以需要填写完整的命名空间描述
// 2.1 创建命令空间描述建造者 => 设计师
NamespaceDescriptor.Builder builder = NamespaceDescriptor.create(namespace);
// 2.2 给命令空间添加需求
builder.addConfiguration("owner", owner);
// 2.3 使用 builder 构造出对应的添加完参数的对象 完成创建
// 创建命名空间出现的问题 都属于本方法自身的问题 不应该抛出
try {
admin.createNamespace(builder.build());
// 3. 关闭 admin
admin.close();
return true;
} catch (IOException e) {
System.out.println("命令空间已经存在");
admin.close();
e.printStackTrace();
return false;
}
}
2、数据表
(1)创建
//创建数据表
@PostMapping("/createTable")
public String initializeHBaseTable(@Valid @RequestBody CreateHbaseTableModel createHbaseTableModel) {
//TODO:需要登录获取用户
String owner="root";
try{
String namespace = createHbaseTableModel.getNamespace();
String tableName = createHbaseTableModel.getTableName();
String[] columnFamilies = createHbaseTableModel.getColumnFamilies();
boolean table = hbaseService.createTable(namespace, tableName, columnFamilies);
if (table){
//TODO:判断该namespace是否有表存在
boolean exists = hbaseService.tableExists(tableName);
if (!exists) {
//保存数据表
HbaseTableEntity tableEntity = new HbaseTableEntity();
tableEntity.setName(tableName);
tableEntity.setOwner(owner);
tableEntity.setNid(namespaceEntityRepository.findByNamespace(namespace).getId());
tableEntityRepository.save(tableEntity);
//保存列族
for (int i = 0; i < columnFamilies.length; i++) {
HbaseColumnfamiliesEntity hbaseColumnfamiliesEntity = new HbaseColumnfamiliesEntity();
hbaseColumnfamiliesEntity.setFamily(columnFamilies[i]);
hbaseColumnfamiliesEntity.setTid(tableEntityRepository.findByName(tableName).getId());
columnfamiliesEntityRepository.save(hbaseColumnfamiliesEntity);
}
return "Table create to HBase successfully!";
}
else{
return "Error checking table existence.";
}
}else {
return "Error create Table to HBase.";
}
} catch (IOException e) {
e.printStackTrace();
return "Error create Table to HBase.";
}
}
Service方法
//创建数据表
public boolean createTable(String namespace, String tableName, String[] columnFamilies) throws IOException {
// 1.获取 admin
Admin admin = hbaseConnection.getAdmin();
TableName hTableName = TableName.valueOf(namespace, tableName);
HTableDescriptor tableDesc = new HTableDescriptor(hTableName);
// 判断是否有至少一个列族
if (columnFamilies.length == 0) {
System.out.println("创建表格至少有一个列族");
return false;
}
// 判断表格是否存在
if (admin.tableExists(hTableName)) {
System.out.println("表格已经存在");
return false;
}
for (String CF : columnFamilies) {
HColumnDescriptor columnFamily = new HColumnDescriptor(CF);
tableDesc.addFamily(columnFamily);
}
admin.createTable(tableDesc);
admin.close();
return true;
}
(2)删除
//删除数据表
@DeleteMapping("/deleteTable")
public String deleteTable(@RequestParam String namespace,@RequestParam String tableName) throws IOException {
hbaseService.deleteTable(namespace,tableName);
Long tableId = tableEntityRepository.findByName(tableName).getId();
List<HbaseColumnfamiliesEntity> columnfamilies = columnfamiliesEntityRepository.findByTid(tableId);
for (int i=0;i<columnfamilies.size();i++){
List<HbaseColumnEntity> column = columnEntityRepository.findByFid(columnfamilies.get(i).getId());
for(int j=0;j<column.size();j++){
columnEntityRepository.deleteById(column.get(j).getId());
}
columnfamiliesEntityRepository.deleteById(columnfamilies.get(i).getId());
}
boolean deletetableById = tableEntityRepository.deleteById(tableId);
if (deletetableById){
return "删除成功";
}else {
return "删除失败";
}
}
Service方法
//删除数据表
public void deleteTable(String namespace, String tableName) throws IOException {
try (Admin admin = hbaseConnection.getAdmin()) {
TableName table = TableName.valueOf(namespace,tableName);
if (admin.tableExists(table)) {
// Disable and delete the table
admin.disableTable(table);
admin.deleteTable(table);
System.out.println("Table " + tableName + " deleted successfully.");
} else {
System.out.println("Table " + tableName + " does not exist.");
}
}
}
(3) 判断数据表是否存在
//数据表是否存在
@GetMapping("/tableExists")
public String tableExists(@RequestParam String tableName) {
try {
boolean exists = hbaseService.tableExists(tableName);
return "Table " + tableName + " exists: " + exists;
} catch (IOException e) {
e.printStackTrace();
return "Error checking table existence.";
}
}
Service方法
// 获取表的元数据
public void getTableMetadata(String tableName) throws IOException {
Admin admin = hbaseConnection.getAdmin();
TableName table = TableName.valueOf(tableName);
if (admin.tableExists(table)) {
HTableDescriptor tableDescriptor = admin.getTableDescriptor(table);
// 获取表名
System.out.println("Table Name: " + tableDescriptor.getTableName());
// 获取列族信息
for (HColumnDescriptor columnDescriptor : tableDescriptor.getColumnFamilies()) {
System.out.println("Column Family: " + columnDescriptor.getNameAsString());
}
} else {
System.out.println("Table does not exist: " + tableName);
}
}
(4)获取数据表元数据
//获取数据表元数据
@GetMapping("/getTableMetadata")
public void getTableMetadata(@RequestParam String tableName) throws IOException {
hbaseService.getTableMetadata(tableName);
}
Service方法
// 获取表的元数据
public void getTableMetadata(String tableName) throws IOException {
Admin admin = hbaseConnection.getAdmin();
TableName table = TableName.valueOf(tableName);
if (admin.tableExists(table)) {
HTableDescriptor tableDescriptor = admin.getTableDescriptor(table);
// 获取表名
System.out.println("Table Name: " + tableDescriptor.getTableName());
// 获取列族信息
for (HColumnDescriptor columnDescriptor : tableDescriptor.getColumnFamilies()) {
System.out.println("Column Family: " + columnDescriptor.getNameAsString());
}
} else {
System.out.println("Table does not exist: " + tableName);
}
}
3、数据
(1)插入数据
//插入数据
@PostMapping("/insertData")
public String putCell(@Valid @RequestBody InsertHbaseDateModel insert){
try{
boolean putCell = hbaseService.putCell(insert.getNamespace(), insert.getTableName(), insert.getRowKey(), insert.getColumnFamily(), insert.getColumnName(), insert.getValue());
if (putCell){
HbaseColumnEntity hbaseColumnEntity=new HbaseColumnEntity();
hbaseColumnEntity.setRowkey(insert.getRowKey());
hbaseColumnEntity.setName(insert.getColumnName());
hbaseColumnEntity.setFid(columnfamiliesEntityRepository.findByFamily(insert.getColumnFamily()).getId());
columnEntityRepository.save(hbaseColumnEntity);
return "Table Insert Data to Table successfully!";
}else {
return "Table Insert Data to Table successfully!";
}
} catch (IOException e) {
e.printStackTrace();
return "Error Insert Data to Table.";
}
}
Service方法
/**
* 插入数据
*
* @param namespace 命名空间名称
* @param tableName 表格名称
* @param rowKey 主键
* @param columnFamily 列族名称
* @param columnName 列名
* @param value 值
*/
public boolean putCell(String namespace, String tableName, String rowKey, String columnFamily, String columnName, String value) throws IOException {
// 1. 获取 table
Table table = hbaseConnection.getTable(TableName.valueOf(namespace, tableName));
// 2. 调用相关方法插入数据
// 2.1 创建 put 对象
Put put = new Put(Bytes.toBytes(rowKey));
// 2.2. 给 put 对象添加数据
put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(columnName), Bytes.toBytes(value));
// 2.3 将对象写入对应的方法
try {
table.put(put);
// 3. 关闭 table
table.close();
return true;
} catch (IOException e) {
e.printStackTrace();
// 3. 关闭 table
table.close();
return false;
}
}
(2)扫描数据
// 扫描数据
@GetMapping("/scanRows")
public void scanRows(@Valid @RequestBody ScanRowsModel scan) throws IOException {
hbaseService.scanRows(scan.getNamespace(),scan.getTableName(),scan.getStartRow(),scan.getStopRow());
}
Service方法
/**
* 扫描数据
*
* @param namespace 命名空间
* @param tableName 表格名称
* @param startRow 开始的 row 包含的
* @param stopRow 结束的 row 不包含
*/
public void scanRows(String namespace, String tableName, String startRow, String stopRow) throws IOException {
// 1. 获取 table
Table table = hbaseConnection.getTable(TableName.valueOf(namespace, tableName));
// 2. 创建 scan 对象
Scan scan = new Scan();
// 如果此时直接调用 会直接扫描整张表
// 添加参数 来控制扫描的数据
// 默认包含
scan.setStartRow(Bytes.toBytes(startRow));
// 默认不包含
scan.setStopRow(Bytes.toBytes(stopRow));
try {
// 读取多行数据 获得 scanner
ResultScanner scanner = table.getScanner(scan);
// result 来记录一行数据 cell 数组
// ResultScanner 来记录多行数据 result 的数组
for (Result result : scanner) {
Cell[] cells = result.rawCells();
for (Cell cell : cells) {
System.out.print(new String(CellUtil.cloneRow(cell)) + "-" + new String(CellUtil.cloneFamily(cell)) + "-" + new String(CellUtil.cloneQualifier(cell)) + "-" + new String(CellUtil.cloneValue(cell)) + "\t");
}
System.out.println();
}
} catch (IOException e) {
e.printStackTrace();
}
// 3. 关闭 table
table.close();
}
(3)读取数据
//读取数据 读取对应的一行中的某一列
@GetMapping("/getCells")
public String getCells(@Valid @RequestBody GetCellHbaseModel getCell) throws IOException {
String cells = hbaseService.getCells(getCell.getNamespace(), getCell.getTableName(), getCell.getRowKey(), getCell.getColumnFamily(), getCell.getColumnName());
return cells;
}
Service方法
/**
* 读取数据 读取对应的一行中的某一列
*
* @param namespace 命名空间名称
* @param tableName 表格名称
* @param rowKey 主键
* @param columnFamily 列族名称
* @param columnName 列名
*/
public String getCells(String namespace, String tableName, String rowKey, String columnFamily, String columnName) throws IOException {
String save = "";
// 1. 获取 table
Table table = hbaseConnection.getTable(TableName.valueOf(namespace, tableName));
// 2. 创建 get 对象
Get get = new Get(Bytes.toBytes(rowKey));
// 如果直接调用 get 方法读取数据 此时读一整行数据
// 如果想读取某一列的数据 需要添加对应的参数
get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(columnName));
// 设置读取数据的版本
get.getMaxVersions();
try {
// 读取数据 得到 result 对象
Result result = table.get(get);
// 处理数据
Cell[] cells = result.rawCells();
// 测试方法: 直接把读取的数据打印到控制台
// 如果是实际开发 需要再额外写方法 对应处理数据
for (Cell cell : cells) {
// cell 存储数据比较底层
String value = new String(CellUtil.cloneValue(cell));
System.out.println(value);
save = value;
}
// 关闭 table
table.close();
return save;
} catch (IOException e) {
// 关闭 table
table.close();
e.printStackTrace();
return save;
}
}
(4)删除数据
//删除 column 数据
@DeleteMapping("/deleteColumn")
public String deleteColumn(@Valid @RequestBody GetCellHbaseModel getCell) throws IOException {
boolean b = hbaseService.deleteColumn(getCell.getNamespace(), getCell.getTableName(), getCell.getRowKey(), getCell.getColumnFamily(), getCell.getColumnName());
if (b){
boolean b1 = columnEntityRepository.deleteById(columnEntityRepository.findByNameAndFidAndRowkey(getCell.getColumnName(), columnfamiliesEntityRepository.findByFamily(getCell.getColumnFamily()).getId(), getCell.getRowKey()).getId());
if (b1){
return "删除成功";
}else {
return "删除失败";
}
}else {
return "删除失败";
}
}
Service方法
/**
* 删除 column 数据
*
* @param nameSpace
* @param tableName
* @param rowKey
* @param family
* @param column
* @throws IOException
*/
public boolean deleteColumn(String nameSpace, String tableName, String rowKey, String family, String column) throws IOException {
// 1.获取 table
Table table = hbaseConnection.getTable(TableName.valueOf(nameSpace, tableName));
// 2.创建 Delete 对象
Delete delete = new Delete(Bytes.toBytes(rowKey));
// 3.添加删除信息
// 3.1 删除单个版本
delete.addColumn(Bytes.toBytes(family), Bytes.toBytes(column));
// 3.2 删除所有版本
delete.addColumns(Bytes.toBytes(family), Bytes.toBytes(column));
// 3.3 删除列族
// delete.addFamily(Bytes.toBytes(family));
// 3.删除数据
table.delete(delete);
// 5.关闭资源
table.close();
return true;
}
四、总结
代码还有很多不完善的地方,有些内容还存在问题,后续需继续完善