HBase之数据操作及自定义元数据存储

一、配置

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;
    }

 四、总结

代码还有很多不完善的地方,有些内容还存在问题,后续需继续完善

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值