一、简介

在上一篇文章 HBase 基础入门 中,我们已经介绍了 HBase 的一些基本概念,以及如何安装使用的方法。

那么,作为一名 Javaer,自然是希望用 Java 的方式来与 HBase 进行对话了。

所幸的是,HBase 本身就是用 Java 编写的,天生自带了 Java 原生API。 我们可以通过 hbase-client 来实现 HBase 数据库的操作。

所以,这次主要介绍该组件的基本用法。

在使用 hbase-client 之前,有几个要点需要注意:

  • 客户端需要能访问 Zoopkeeper,再获得 HMaster、RegionServer 实例进行操作
  • 客户端需运行在HBase/Hadoop 集群内,HBase会使用 hostname 来定位节点,因此要求客户端能访问到对应的主机名(或子域名)

    如果是远程客户端则需要配置本地的hosts文件。

下面这个图,有助于理解 Client 与 HBase 集群的交互架构:

下面开始介绍 client 的使用。

二、hbase-client 引入

在 Maven 的 pom.xml 中添加依赖:

<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.1.5</version>
<exclusions>
<exclusion>
<artifactId>slf4j-api</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase</artifactId>
<version>2.1.5</version>
</dependency>

这里需要注意的是,客户端版本和 HBase 版本需要保持一致,否则可能会遇到不兼容的问题。

三、连接操作

示例代码:

/**
* 建立连接
*
* @return
*/
public static Connection getConnection() {
try {
//获取配置
Configuration configuration = getConfiguration();
//检查配置
HBaseAdmin.checkHBaseAvailable(configuration);
return ConnectionFactory.createConnection(configuration);
} catch (IOException | ServiceException e) {
throw new RuntimeException(e);
}
} /**
* 获取配置
*
* @return
*/
private static Configuration getConfiguration() {
try {
Properties props = PropertiesLoaderUtils.loadAllProperties("hbase.properties");
String clientPort = props.getProperty("hbase.zookeeper.property.clientPort");
String quorum = props.getProperty("hbase.zookeeper.quorum"); logger.info("connect to zookeeper {}:{}", quorum, clientPort); Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.property.clientPort", clientPort);
config.set("hbase.zookeeper.quorum", quorum);
return config;
} catch (IOException e) {
throw new RuntimeException(e);
}
}

四、表操作

增删改查方法封装如下:

/**
* 创建表
* @param connection
* @param tableName
* @param columnFamilies
* @throws IOException
*/
public static void createTable(Connection connection, TableName tableName, String... columnFamilies) throws IOException {
Admin admin = null;
try {
admin = connection.getAdmin();
if (admin.tableExists(tableName)) {
logger.warn("table:{} exists!", tableName.getName());
} else {
TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(tableName);
for (String columnFamily : columnFamilies) {
builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(columnFamily));
}
admin.createTable(builder.build());
logger.info("create table:{} success!", tableName.getName());
}
} finally {
if (admin != null) {
admin.close();
}
}
} /**
* 插入数据
*
* @param connection
* @param tableName
* @param rowKey
* @param columnFamily
* @param column
* @param data
* @throws IOException
*/
public static void put(Connection connection, TableName tableName,
String rowKey, String columnFamily, String column, String data) throws IOException { Table table = null;
try {
table = connection.getTable(tableName);
Put put = new Put(Bytes.toBytes(rowKey));
put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(data));
table.put(put);
} finally {
if (table != null) {
table.close();
}
}
} /**
* 根据row key、column 读取
*
* @param connection
* @param tableName
* @param rowKey
* @param columnFamily
* @param column
* @throws IOException
*/
public static String getCell(Connection connection, TableName tableName, String rowKey, String columnFamily, String column) throws IOException {
Table table = null;
try {
table = connection.getTable(tableName);
Get get = new Get(Bytes.toBytes(rowKey));
get.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column)); Result result = table.get(get);
List<Cell> cells = result.listCells(); if (CollectionUtils.isEmpty(cells)) {
return null;
}
String value = new String(CellUtil.cloneValue(cells.get(0)), "UTF-8");
return value;
} finally {
if (table != null) {
table.close();
}
}
} /**
* 根据rowkey 获取一行
*
* @param connection
* @param tableName
* @param rowKey
* @return
* @throws IOException
*/
public static Map<String, String> getRow(Connection connection, TableName tableName, String rowKey) throws IOException {
Table table = null;
try {
table = connection.getTable(tableName);
Get get = new Get(Bytes.toBytes(rowKey)); Result result = table.get(get);
List<Cell> cells = result.listCells(); if (CollectionUtils.isEmpty(cells)) {
return Collections.emptyMap();
}
Map<String, String> objectMap = new HashMap<>();
for (Cell cell : cells) {
String qualifier = new String(CellUtil.cloneQualifier(cell));
String value = new String(CellUtil.cloneValue(cell), "UTF-8");
objectMap.put(qualifier, value);
}
return objectMap;
} finally {
if (table != null) {
table.close();
}
}
} /**
* 扫描权标的内容
*
* @param connection
* @param tableName
* @param rowkeyStart
* @param rowkeyEnd
* @throws IOException
*/
public static List<Map<String, String>> scan(Connection connection, TableName tableName, String rowkeyStart, String rowkeyEnd) throws IOException {
Table table = null;
try {
table = connection.getTable(tableName);
ResultScanner rs = null;
try {
Scan scan = new Scan();
if (!StringUtils.isEmpty(rowkeyStart)) {
scan.withStartRow(Bytes.toBytes(rowkeyStart));
}
if (!StringUtils.isEmpty(rowkeyEnd)) {
scan.withStopRow(Bytes.toBytes(rowkeyEnd));
}
rs = table.getScanner(scan); List<Map<String, String>> dataList = new ArrayList<>();
for (Result r : rs) {
Map<String, String> objectMap = new HashMap<>();
for (Cell cell : r.listCells()) {
String qualifier = new String(CellUtil.cloneQualifier(cell));
String value = new String(CellUtil.cloneValue(cell), "UTF-8");
objectMap.put(qualifier, value);
}
dataList.add(objectMap);
}
return dataList;
} finally {
if (rs != null) {
rs.close();
}
}
} finally {
if (table != null) {
table.close();
}
}
} /**
* 删除表
*
* @param connection
* @param tableName
* @throws IOException
*/
public static void deleteTable(Connection connection, TableName tableName) throws IOException {
Admin admin = null;
try {
admin = connection.getAdmin();
if (admin.tableExists(tableName)) {
//现执行disable
admin.disableTable(tableName);
admin.deleteTable(tableName);
}
} finally {
if (admin != null) {
admin.close();
}
}
}

五、运行测试

最后,我们仍然以上一篇文章中的设备数据作为例子:

  1. 建立 DeviceState 表;
  2. 定义 name/state 两个列簇;
  3. 写入列数据;
  4. 读取列、行,范围读取;
  5. 删除操作

最终实现的代码如下:

private static final Logger logger = LoggerFactory.getLogger(HBaseTest.class);

public static void main(String[] args) {

    Connection connection = null;
try {
connection = getConnection();
TableName tableName = TableName.valueOf("DeviceState"); //创建DeviceState表
createTable(connection, tableName, "name", "state"); logger.info("创建表 {}", tableName.getNameAsString()); //写入数据
put(connection, tableName, "row1", "name", "c1", "空调");
put(connection, tableName, "row1", "state", "c2", "打开");
put(connection, tableName, "row2", "name", "c1", "电视机");
put(connection, tableName, "row2", "state", "c2", "关闭"); logger.info("写入数据."); String value = getCell(connection, tableName, "row1", "state", "c2");
logger.info("读取单元格-row1.state:{}", value); Map<String, String> row = getRow(connection, tableName, "row2");
logger.info("读取单元格-row2:{}", JsonUtil.toJson(row)); List<Map<String, String>> dataList = scan(connection, tableName, null, null);
logger.info("扫描表结果-:\n{}", JsonUtil.toPrettyJson(dataList)); //删除DeviceState表
deleteTable(connection, tableName);
logger.info("删除表 {}", tableName.getNameAsString()); logger.info("操作完成.");
} catch (Exception e) {
logger.error("操作出错", e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (IOException e) {
logger.error("error occurs", e);
}
}
} }

执行代码,控制台输出如下:

INFO -createTable(HBaseTest.java:89) - create table:[68, 101, 118, 105, 99, 101, 83, 116, 97, 116, 101] success!
INFO -main(HBaseTest.java:32) - 创建表 DeviceState
INFO -main(HBaseTest.java:40) - 写入数据.
INFO -main(HBaseTest.java:43) - 读取单元格-row1.state:打开
INFO -main(HBaseTest.java:46) - 读取单元格-row2:{"c1":"电视机","c2":"关闭"}
INFO -main(HBaseTest.java:49) - 扫描表结果-:
[ {
"c1" : "空调",
"c2" : "打开"
}, {
"c1" : "电视机",
"c2" : "关闭"
} ]
INFO -HBaseAdmin$9.call(HBaseAdmin.java:1380) - Started disable of DeviceState
INFO -HBaseAdmin$DisableTableFuture.postOperationResult(HBaseAdmin.java:1409) - Disabled DeviceState
INFO -HBaseAdmin$DeleteTableFuture.postOperationResult(HBaseAdmin.java:965) - Deleted DeviceState
INFO -main(HBaseTest.java:53) - 删除表 DeviceState
INFO -main(HBaseTest.java:55) - 操作完成.

此时Java Client已经完成制作。

FAQ

  • 提示报错 找不到winutils程序

Failed to locate the winutils binary in the hadoop binary path

原因是在Windows下依赖一个winutils.exe程序,该程序通过${HADOOP_HOME}/bin 来查找。

该报错不影响程序执行,但如果要规避问题,需要下载hadoop-commons-master,再配置变量HADOOP_HOME

可参考地址:https://blog.csdn.net/ycf921244819/article/details/81706119

  • 提示报错,UnknownHostException,无法找到节点..

    原因是客户端无法解析HMaster实例节点的主机名

    需要编辑 C:\Windows\System32\drivers\etc\hosts 文件,添加对应的映射,如下:
47.xx.8x.xx izwz925kr63w5jitjys6dtt

参考文档

官方文档

https://hbase.apache.org/book.html#quickstart

Java HBase客户端API

https://www.baeldung.com/hbase

HBase(2) Java 操作 HBase 教程的更多相关文章

  1. 【hbase】——Java操作Hbase进行建表、删表以及对数据进行增删改查,条件查询

    1.搭建环境 新建JAVA项目,添加的包有: 有关Hadoop的hadoop-core-0.20.204.0.jar 有关Hbase的hbase-0.90.4.jar.hbase-0.90.4-tes ...

  2. Java 操作 HBase 教程

    Java 操作 HBase 教程 一.简介 二.hbase-client 引入 三.连接操作 四.表操作 五.运行测试 相关博文原文地址: 博客园:美码师:HBase(2) Java 操作 HBase ...

  3. Hbase深入学习(六) Java操作HBase

    Hbase深入学习(六) ―― Java操作HBase 本文讲述如何用hbase shell命令和hbase java api对hbase服务器进行操作. 先看以下读取一行记录hbase是如何进行工作 ...

  4. Java操作hbase总结

    用过以后,总得写个总结,不然,就忘喽. 一.寻找操作的jar包. java操作hbase,首先要考虑到使用hbase的jar包. 因为咱装的是CDH5,比较方便,使用SecureCRT工具,远程连接到 ...

  5. java操作Hbase实例

    所用HBase版本为1.1.2,hadoop版本为2.4 /* * 创建一个students表,并进行相关操作 */ import java.io.IOException; import java.u ...

  6. HBase的java操作,最新API。(查询指定行、列、插入数据等)

    关于HBase环境搭建和HBase的原理架构,请见笔者相关博客. 1.HBase对java有着较优秀的支持,本文将介绍如何使用java操作Hbase. 首先是pom依赖: <dependency ...

  7. 错误: 找不到或无法加载主类 java操作hbase出错

    用java操作hbase 利用maven引入hbase包后发现无法启动程序,然后网上说是包的冲突. 我引入了下面三个包然后程序就不能运行了. <dependency> <groupI ...

  8. HBase篇--HBase操作Api和Java操作Hbase相关Api

    一.前述. Hbase shell启动命令窗口,然后再Hbase shell中对应的api命令如下. 二.说明 Hbase shell中删除键是空格+Ctrl键. 三.代码 1.封装所有的API pa ...

  9. HBASE学习d端口master:16010(java操作hbase)https://www.cnblogs.com/junrong624/p/7323483.html

    HBase提示已创建表,但是list查询时,却显示表不存在. https://blog.csdn.net/liu16659/article/details/80216085 下载网址 http://a ...

随机推荐

  1. 原生JS封装_new函数,实现new关键字的功能

    1.前言 众所周知:没有对象怎么办?那就new一个! 那么在JS中,当我们new一个对象的时候,这个new关键字内部都干了什么呢? 现在我们就来剖析一下原生JS中new关键字内部的工作原理. 2.原生 ...

  2. web应用安全框架选型:Spring Security与Apache Shiro

    一. SpringSecurity 框架简介 官网:https://projects.spring.io/spring-security/ 源代码: https://github.com/spring ...

  3. javascript关于box2djs和matterjs之间的选择

    javascript关于box2djs和matterjs之间的选择box2djs资料少很多时候需要看c++版本资料 然后转化成js 还有转化成像素坐标不准确 matterjs文档丰富 上手容易 建议用 ...

  4. maven安装与在eclipse中配置

    需要准备 eclipse maven压缩包 : http://maven.apache.org/download.cgi 1 解压maven压缩包 2 在系统变量中新建变量MAVEN_HOME,值为 ...

  5. X-Admin&ABP框架开发-RBAC

    在业务系统需求规划过程中,通常对于诸如组织机构.用户和角色等这种基础功能,通常是将这部分功能规划到通用子域中,这也说明了,对于这部分功能来讲,是系统的基石,整个业务体系是建立于这部分基石之上的,当然, ...

  6. Java设计模式(20):命令模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 智能电脑的品牌越来越多,由此诞生了一款电脑控制的APP,万能遥控器,用户在使用遥控器的时候,可以切换为自家电视的品 ...

  7. shell中tar加密打包

    tar 打包是一个很常见的操作,但是当打了一个包却又不想让别人看到里面的小秘密的时候就可以使用加密的方法进行打包. 以下是一个脚本实现的加密打包和解密的shell脚本: cat tar_passwor ...

  8. 力扣(LeetCode)二进制求和 个人题解

    给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = "11", b = "1" 输出: ...

  9. Java描述设计模式(21):状态模式

    本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.场景描述 变色龙是爬行动物,是非常奇特的动物,它有适于树栖生活的种种特征和行为,身体也会随着环境的变化而变化出适应环境的颜色 ...

  10. MachO文件详解--逆向开发

    今天是逆向开发的第5天内容--MachO文件(Mac 和 iOS 平台可执行的文件),在逆向开发中是比较重要的,下面我们着重讲解一下MachO文件的基本内容和使用. 一.MachO概述 1. 概述 M ...