# HydraQL
**Repository Path**: jjfinal/hydra-ql
## Basic Information
- **Project Name**: HydraQL
- **Description**: `HydraQL`是基于HBase的client API设计的一款SQL查询器,专为简化HBase原生API的使用而打造。
`HydraQL`旨在提供一种更直观、易用的方式来查询和操作HBase数据库。通过使用SQL语法或更精简的API,用户可以通过简单的查询语句访问和操作HBase中的数据,而无需深入了解和编写复杂的`hbase-client`API调用。
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 13
- **Created**: 2024-07-16
- **Last Updated**: 2024-07-16
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
🍬 HydraQL [ˈhaɪdrəQL],是基于HBase原生客户端API设计的一款SQL查询器,专为简化HBase的使用而打造。
👉 https://hydraql.com/ 👈
-------------------------------------------------------------------------------
[**🌎English Documentation**](README-EN.md)
-------------------------------------------------------------------------------
## 📚简介
`HydraQL` 是基于 `hbase-clinet` API设计的一款SQL查询器,专为简化HBase的使用而打造。
`HydraQL`旨在提供一种更直观和易用的方式来查询和操作HBase数据库。通过使用SQL语法或更精简的API,
用户就可以轻松读写HBase表中的数据,而无需深入了解和编写复杂的方法调用。
与Phoenix相比,`HydraQL`中的SQL语法更轻量,无需引入额外的组件和配置即可使用,但目前还不支持二级索引。
### 🎁HydraQL的名称由来
`HydraQL`由Hydra + SQL 拼接而来,其名称**Hydra**引用了“九头蛇”,象征着在处理HBase数据时的灵活性和多功能性。
**hql** 是其简称,一种类SQL的语言,其在执行时,会被翻译成`hbase-client`的原生API来读写HBase表中的数据。
### 🍺HydraQL的理念
`HydraQL` 是HBase的衍生工具集,它融合了hql、HBatis、hbase-shell、hbase-thrift等API的功能,你可以按需引用,也可以**拷贝**和修改源码使用,
这并不会有什么限制,只希望能及时反馈bug,或提供更好的建议。
-------------------------------------------------------------------------------
## ⚙️模块信息
项目结构:
```shell
├── LICENSE
├── README.md
├── antlr
├── bin
├── build
├── hydraql-adapter
│ ├── hydraql-adapter-common
│ ├── hydraql-adapter_1.2
│ ├── hydraql-adapter_1.4
│ ├── hydraql-adapter_2.2
├── hydraql-common
├── hydraql-console
├── hydraql-dsl
├── hydraql-examples
├── hydraql-tests
│ ├── hydraql-example
│ ├── hydraql-shell-example
│ └── spring-boot-starter-hydraql-example
├── hydraql-shell
│ ├── hydraql-shell-core
│ ├── hydraql-shell_1.2
│ ├── hydraql-shell_1.4
│ ├── hydraql-shell_2.2
├── hydraql-template
├── hydraql-thrift
└── spring-boot-starter-hydraql
```
核心模块介绍:
| 模块 | 介绍 |
|-----------------------------|-----------------------------------------------------------------------------|
| hydraql-common | 对一些公共方法的封装 |
| hydraql-dsl | hql的定义,以及使用antr4解析hql,并转换hbase-client的调用 |
| hydraql-adapter | 统一HBase数据读写的接口,并针对不同版本的`hbase-client` api进行适配和增强,屏蔽了多版本下hbase-client api不兼容 |
| hydraql-template | 依赖hydraql-adapter,对外统一暴露为模版类和模版方法 |
| hydraql-tests | 利用HBaseMiniCluster来做单元测试 |
| spring-boot-starter-hydraql | 可以利用spring-boot-starter-hydraql与Spring Boot轻松集成 |
| hydraql-thrift | 对HBase thrift API的池化和封装 |
| hydraql-shell | 对HBase Shell的封装,支持直接在java进程中执行hbase-shell的JRuby环境,可以利用该模块,封装web-hbase-shell |
| hydraql-console | hql的命令行交互程序 |
## 🛠️功能特性
对`hbase-client`原生API进行了统一的接口定义,屏蔽了底层API的复杂调用方式,消除了跨版本升级过程中API不兼容的问题。
在保障原有功能的同时,额外扩展了其他优秀特性,列举如下:
* [x] 定义了统一的接口规范,消除了不同版本`hbase-client`API之间的差异
* [x] HQL,以类SQL的形式读写HBase的表中数据
* [x] HBatis, 类似MyBatis,提供**ORM**的特性,支持以注解的方式快速定义表、列簇、字段的数据模型,在保存和查询数据时,底层自动做数据类型转换
* [x] 对HBase的原生thrift API进行池化封装,提供了HBaseThriftPool的功能
* [x] 利用spring-boot-starter-hydraql可与SpringBoot无缝集成
* [x] 支持kerberos认证,支持kerberos认证的超级用户代理普通用户
* [x] 支持类似hdfs的hbase.client.hedged.read功能,在读主集群达到超时阈值或异常时,自动降级读备集群数据,此功能要求HBase主备集群互相Replication
* [x] hydraql-shell,把hbase-shell封装到一个jar包中,可被其他项目通过maven等方式依赖,这在你想开发hbase-web-shell的功能时非常有用
* [x] hydraql-console,命令行交互工具,可以同时执行hql和hbase-shell的指令,可完全替代hbase-shell来使用
* [ ] HBatis,类似于myBatis,提供配置文件管理HQL的功能(规划中)
* [ ] thrift 连接池中连接数的动态扩所容能力(规划中)
-------------------------------------------------------------------------------
## 📝文档
[📘中文文档](https://www.docs.hydraql.com)
[📙参考API](https://apidoc.gitee.com/weixiaotome/HydraQL/)
[🎬视频介绍](https://www.bilibili.com/video/B)
-------------------------------------------------------------------------------
## 🪙支持HydraQL
### 💳捐赠
如果你觉得HydraQL不错,可以请维护者吃包辣条~,在此表示感谢^_^。
-------------------------------------------------------------------------------
## 📦使用指南
### 🍊Maven
在普通maven项目中使用,在项目的pom.xml的dependencies中加入以下内容:
```xml
1.2
com.hydraql
hydraql-template_${hydraql.hbase.adapter.version}
1.0.0
```
在Spring Boot项目中使用,在项目的pom.xml的dependencies中加入以下内容:
```xml
1.2
com.hydraql
spring-boot-starter-hydraql_${hydraql.hbase.adapter.version}
1.0.0
```
根据所需hbase的版本来指定不同的`hydraql.hbase.adapter.version`,目前支持的hbase版本有:1.2.x,1.4.x,2.0.x ~ 2.2.x,
更多HBase版本的支持还在持续构建中 ~
- [Maven中央库](https://repo1.maven.org/maven2/com/hydraql/hydraql/1.0.0/)
> 🔔️注意
> 最新版本的发行包可能更新不及时,同时,hydraql在构建发行包时,默认把hbase--shaded-client的依赖一起打包。
> 如果对hbase的版本要求强一致,可以选择修改hbase-client的版本后,自行编译安装,再在项目中引入
### 🍐Gradle
```
implementation 'com.hydraql:hydraql-template_1.2:1.0.0'
implementation 'com.hydraql:hydraql-template_1.4:1.0.0'
implementation 'com.hydraql:hydraql-template_2.2:1.0.0'
```
### 🚽编译安装
访问`HydraQL`的GItHub主页:[https://github.com/CCweixiao/HydraQL](https://github.com/CCweixiao/HydraQL) 下载整个项目源码(master分支)然后进入HydraQL项目的根目录下执行:
```sh
sh bin/build.sh 1.2/1.4/2.2
```
或
```shell
# 默认1.2
mvn clean install -Dmaven.test.skip=true
# 1.4
mvn clean install -Dmaven.test.skip=true -Dhbase.profile=1.4
# 2.2
mvn clean install -Dmaven.test.skip=true -Dhbase.profile=2.2
```
如果你想在本地进行开发,扩展额外的功能,请确保已经安装了Java8和maven3.6+,同时建议在本地部署一个可连通的HBase开发环境。
建议使用docker来快速搭建一个HBase的单机环境,可以参考博客:https://blog.csdn.net/feinifi/article/details/121174846
### 快速入门
```java
@Test
public void testSaveAndGet(){
Configuration conf = HBaseConfiguration.create();
HBaseTableTemplate tableTemplate = HBaseTableTemplate.of(conf);
Map data = new HashMap<>(2);
data.put("f1:name", "leo");
data.put("f1:age", 18);
tableTemplate.save("test_table", "1001", data);
HBaseRowData rowData = tableTemplate.getRow("test_table", GetRowParam.of("1001").build());
}
```
更多测试用例请参考:[更多测试用例](https://github.com/CCweixiao/HydraQL/blob/master/hydraql-tests/hydraql-template-test/src/test/java/com/hydraql/template/HBaseTableTestTemplateTest.java)
## 使用手册
### 连接配置
**普通Java项目**
**普通认证**
```java
// 普通认证
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "myhbase");
conf.set("hbase.zookeeper.property.clientPort", "2181");
// 请按需引入一些额外所需的客户端配置
conf.set("hbase.client.retries.number", "3");
HBaseTableTemplate tableTemplate = HBaseTableTemplate.of(conf);
```
或者在项目的src/main/resources目录下放入`hbase-site.xml`配置文件
**Kerberos认证**
```java
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "zk1,zk2,zk3");
conf.set("hbase.zookeeper.property.clientPort", "2181");
conf.set("hbase.security.authentication", "kerberos");
// 下面配置是kerberos认证方式所需
conf.set("kerberos.principal", "hbase@HADOOP.LEO.COM");
conf.set("keytab.file", "/etc/hbase/conf/hbase.keytab");
// 设置kerberos代理用户,默认为空即不进行设置,需保证hbase有代理其他用户的权限
conf.set("kerberos.proxy.user", "leojie");
conf.set("hbase.regionserver.kerberos.principal", "hbase/_HOST@HADOOP.LEO.COM");
conf.set("hbase.master.kerberos.principal", "hbase/_HOST@HADOOP.LEO.COM");
// 指定kdc服务相关的配置方式有如下两种:
// 方式一:指定krb5.conf路径
conf.set("java.security.krb5.conf", "/etc/krb5.conf");
// 方式二:指定java.security.krb5.realm和java.security.krb5.kdc
// conf.set("java.security.krb5.realm", "HADOOP.LEO.COM");
// conf.set("java.security.krb5.kdc", "你自己的kdc服务地址");
// 一些额外的客户端参数
conf.set("hbase.client.retries.number", "3");
HBaseTableTemplate tableTemplate = HBaseTableTemplate.of(conf);
```
**Spring Boot项目**
**普通认证**
application.yaml
```yaml
spring:
datasource:
hbase:
zk-quorum: zk_host1,zk_host2,zk_host3
zk-client-port: 2181 # (可选,默认2181)
dfs-root-dir: /hbase # (可选,默认/hbase)
zk-node-parent: /hbase # (可选,默认/hbase)
security-auth-way: simple # (可选,默认simple)
client-properties: hbase.client.retries.number=3;key1=value2
server:
port: 8088
```
**Kerberos认证**
```yaml
spring:
datasource:
hbase:
zk-quorum: myhbase
zk-client-port: 2181
dfs-root-dir: /hbase
zk-node-parent: /hbase
security-auth-way: kerberos
kerberos-principal: hbase@HADOOP.LEO.COM
keytab-file-path: /etc/hbase/conf/hbase.keytab
kerberos-proxy-user: test
rs-kerberos-principal: hbase/_HOST@HADOOP.LEO.COM
master-kerberos-principal: hbase/_HOST@HADOOP.LEO.COM
krb5-conf-path: /etc/krb5.conf
krb5-realm:
krb5-kdc-server-addr:
client-properties: hbase.client.retries.number=3
server:
port: 8088
```
```java
@Service
public class HBaseAdminService {
@Autowired
private BaseHBaseAdminTemplate adminTemplate;
public List allTables() {
return adminTemplate.listTableNames();
}
}
```
### hydraql-template模块介绍
`hydraql-template`模块中封装了三类模版操作类,分别是:
- HBaseAdminTemplate: 对Admin中方法的封装,比如:创建表,创建namespace,list表等
- HBaseTableTemplate: 对Table中方法的封装,比如:put,get,scan,delete等
- HBaseSqlTemplate: 提供hql的功能

**普通项目**
```java
// 数据读写API的操作模版类
Configuration conf = HBaseConfiguration.create();
BaseHBaseTableTemplate tableTemplate = HBaseTableTemplate.of(conf);
// Admin操作模版类
BaseHBaseAdminTemplate adminTemplate = HBaseAdminTemplate.of(conf);
// HQL操作模版类
BaseHBaseSqlTemplate sqlTemplate = HBaseSqlTemplate.of(conf);
```
**SpringBoot项目**
@Autowired 依赖注入
```java
@Service
public class UserService {
@Autowired
private BaseHBaseTableTemplate tableTemplate;
@Autowired
private BaseHBaseAdminTemplate adminTemplate;
@Autowired
private BaseHBaseSqlTemplate sqlTemplate;
}
```
### BaseHBaseAdminTemplate使用
`BaseHBaseAdminTemplate`封装了`hbase-client`中Admin的常用操作,比如namespace的创建和删除、表的创建和删除、以及快照管理等等,后续这些API将会更加完整。

**创建namespace**
```java
@Test
public void createNameSpace() {
NamespaceDesc namespaceDesc = new NamespaceDesc();
namespaceDesc.setNamespaceName("test_nn");
namespaceDesc.addNamespaceProp("createdBy", "leojie");
adminTemplate.createNamespaceAsync(namespaceDesc);
}
```
**创建表**
```java
@Test
public void testCreateTable() {
ColumnFamilyDesc f1 = ColumnFamilyDesc.newBuilder()
.name("f1")
.build();
ColumnFamilyDesc f2 = ColumnFamilyDesc.newBuilder()
.name("f2")
.timeToLive(3600)
.maxVersions(3)
.build();
HTableDesc tableDesc = HTableDesc.newBuilder()
.name("leo_test_22222")
.addFamilyDesc(f1)
.addFamilyDesc(f2)
.build();
adminTemplate.createTable(tableDesc);
}
```
更多测试用例请参考 `hydraql-tests`模块
### BaseHBaseTableTemplate使用
`BaseHBaseTableTemplate`中封装了对HBase表数据的读、写、删除等操作。
**普通方式读写**
```java
@Test
public void testSaveMap() {
Map data = new HashMap<>(2);
data.put("f1:name", "leo");
data.put("f1:age", 18);
tableTemplate.save(TEST_TABLE, "1001", data);
HBaseRowData rowData = tableTemplate.getRow(TEST_TABLE, GetRowParam.of("1001").build());
Assert.assertEquals(2, rowData.getColDataContainer().size());
}
```
**ORM特性**
1. 创建数据模型类
```java
public class CityTag {
private String tagName;
public CityTag(String tagName) {
this.tagName = tagName;
}
// 省略Getter/Setter/toString
}
```
```java
@HBaseTable(namespaceName = "default", tableName = "test_table", defaultFamilyName = "f1")
public class CityModel {
@HBaseRowKey
private String cityId;
private String cityName;
private String cityAddress;
@HBaseColumn(familyName = "detail")
private Integer cityArea;
@HBaseColumn(familyName = "detail", toUpperCase = true)
private Integer totalPopulation;
@HBaseColumn(familyName = "detail", columnName = "cityTagList")
private List cityTagList;
// 省略Getter/Setter/toString
}
```
`@HBaseTable`注解用于定义HBase的表信息
```java
@HBaseTable(namespaceName = "default", tableName = "t2", defaultFamilyName = "info")
```
1)namespaceName:用于指定该表的命名空间,默认:default
2)tableName:用于指定该表的表名,如果不指定,表名则为类名的组合单词拆分转小写加'_'拼接,如:CityModel对应的表名为:city_model。
3)defaultFamilyName:用于定义如果有字段不特配置(@HBaseRowKey注解中的familyName)列簇名,则使用此处配置的列簇名。
`@HBaseRowKey`注解用于定义某一个属性字段是用作存储rowKey数据的,是必须要设置的,如:
```java
@HBaseRowKey
private String cityId;
```
该注解表示cityId字段为rowKey,每一个模型类必须,也只能有一个字段被标识为rowKey。
`@HBaseColumn`注解用于定义HBase的列簇和列名信息,如:
```java
@HBaseColumn(familyName = "detail", columnName = "TOTAL_POPULATION", toUpperCase = true)
private Integer totalPopulation;
```
1)familyName:指定列簇名,不指定,则使用defaultFamilyName配置的列簇名。
2)columnName:指定列名,不指定则默认使用字段名的组合单词拆分转小写加'_'拼接,如:isVip,对应的字段名是:is_vip
3)toUpperCase:定义字段名是否转大写,如:isVip -> IS_VIP,默认值:false,不做转换。
2. 存取数据
```java
@Test
public void testSave() {
CityModel cityModel = CityModelUtil.createDefaultCityModel();
tableTemplate.save(cityModel);
GetRowParam getRowParam = GetRowParam.of(cityModel.getCityId()).build();
Optional cityModelRes = tableTemplate.getRow(getRowParam, CityModel.class);
Assert.assertNotNull(cityModelRes);
}
```
3. 批量存取数据
```java
@Test
public void testSaveBatch() {
List cityModelList = CityModelUtil.createDefaultCityModelList();
tableTemplate.saveBatch(cityModelList);
List rowKeys = cityModelList.stream().map(CityModel::getCityId).collect(Collectors.toList());
GetRowsParam getRowsParam = GetRowsParam.of().rowKeyList(rowKeys).build();
List rows = tableTemplate.getRows(getRowsParam, CityModel.class);
Assert.assertEquals(rowKeys.size(), rows.size());
}
```
4. 查询数据使用自定义的RowMapper解析字段
```java
@Test
public void testGetByRowMapper() {
GetRowParam getRowParam = GetRowParam.of("a10001").build();
Map data = tableTemplate.getRow(TEST_TABLE, getRowParam, new RowMapper