作业一:Java远程连接+CRUD Ubuntu下HBase
一. 准备工作以及使用工具
注:因为习惯原因,本次实验使用idea工具完成,这个文章也给想使用idea工具去完成作业的同学一个参考。
idea编辑工具 maven项目管理和构建自动化工具 java1.8 部署好的Ubuntu虚拟机和配置好的Hbase FinalShell 远程连接虚拟机工具
二.作业步骤
1.配置window的hosts。
将Ubuntu虚拟机的ip设置为静态ip,使用 ifconfig 命令进行查看,其中192.168.88.131就是ip地址,找到windows目录下的hosts文件存放地址 C:\Windows\System32\drivers\etc 将静态ip和代表域名写入保存。
ifconfig
2. 使用idea创建maven项目,并做好相关配置。
2.1 创建maven项目。
选择好直接保存的路径,方便管理,项目名称取为work1
2.2 编写maven的pom.xml文件。
使用坐标导入仓库的bhase相关依赖,只需要这样,maven仓库就会自己自动下载bhase API的相关jar包,由于我们还需要使用测试,所以我们要导入junit 和 log4j坐标备用。
`在这里插入代码片`
2.3 编写java代码使用 hbase API 连接hbase的代码
2.3.1HbaseConnection.java
注:因为老师截图代码好像因为版本古老,里面的一些API也已经被删除了,所以我写的代码与老师写的会有一些差异,,但是大体功能是一样的。
在连接方法上,我使用了static 单例连接,代码如下。也就是在HbaseConnection 可以被直接使用,不用new,在HbaseConnection被使用时,connection就会开始和虚拟机的hbase连接 。
public class HbaseConnection {
public static Connection connection = null;
// 静态的连接
static {
try {
connection = ConnectionFactory.createConnection();
System.out.println("数据库连接成功");
} catch (IOException e) {
System.out.println("数据库连接失败");
e.printStackTrace();
}
}
// 关闭连接
public static void closeConnection() throws IOException {
// 判断连接是否为null
if (connection != null){
connection.close();
}
}
}
大家会发现这个代码和老师的有太多地方不一样了:configuration在哪去了,没有配置项如何建立连接?
configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum", "node1");
这个需要翻看文档和看源码来理解,我在这简单说一下:在这个方法connection = ConnectionFactory.createConnection();使用时,其实还要又有这个方法,它的内部,HBaseConfiguration被重载了,慢慢往下找,就会发现他最终会去work1项目文件下的 resources资源目录,我们只要将,hbase-site.xml等相关配置项复制过来就可以了。
2.3.2 HBaseCRUD.java
这个java类,通过HbaseConnection.java连接 hbase 后,完成相关的CRUD操作,也就是数据库的增删改查。我改了一些写法,但是大体没有动,但在写代码时,idea 提示很多的API已经弃用了,虽然还可以跑起来,但是官方是不推荐的。
这块代码没有什么好说的,他的逻辑是很接近 hbase shell 的,我们要分清楚的还是Hbase数据库的结构,也就是,表(table),行键(Row Key),列族(columnFamilies),时间戳(Timestamp)。
package org.example;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
import java.util.List;
/**
* HBaseCRUD类提供了对HBase数据库进行创建、读取、更新和删除操作的方法。
*/
public class HBaseCRUD {
public Connection hbaseConnection;
public Admin admin;
TableName tableName;
HTableDescriptor tableDescriptor;
HColumnDescriptor hColumnDescriptor;
Table table;
/**
* HBaseCRUD构造函数,初始化HBase连接和管理员对象。
*/
public HBaseCRUD(){
hbaseConnection = HbaseConnection.connection;
getAdmin();
}
/**
* 获取HBase管理员对象。
*/
public void getAdmin(){
try {
admin = hbaseConnection.getAdmin();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 根据表名获取表对象。
*
* @param name 表的名称。
* @return 返回对应的Table对象。
* @throws IOException 如果发生IO异常。
*/
public Table getTable(String name) throws IOException {
table = hbaseConnection.getTable(TableName.valueOf(name));
return table;
}
/**
* 创建新表。
*
* @param name 表的名称。
* @param columnFamilies 列族数组。
* @throws IOException 如果发生IO异常。
*/
public void createTable(String name, String[] columnFamilies) throws IOException {
tableName = TableName.valueOf(name);
if (admin.tableExists(tableName)){
admin.disableTable(tableName);
admin.deleteTable(tableName);
System.out.println(tableName.toString() + "is exists is deleted");
}
tableDescriptor = new HTableDescriptor(tableName);
for(String columnFamily : columnFamilies){
hColumnDescriptor = new HColumnDescriptor(columnFamily);
tableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(tableDescriptor);
System.out.println("Table is created");
}
/**
* 向表中插入或修改数据。
*
* @param name 表的名称。
* @param rowKey 行键。
* @param columnFamily 列族。
* @param columnName 列名。
* @param timeStamp 时间戳。
* @param value 要插入或修改的值。
* @throws IOException 如果发生IO异常。
*/
public void insertAndModify(String name, String rowKey, String columnFamily,
String columnName, Long timeStamp, String value) throws IOException {
getTable(name);
Put put = new Put(Bytes.toBytes(rowKey));
put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(columnName), timeStamp, Bytes.toBytes(value));
table.put(put);
table.close();
}
/**
* 根据行键和列名获取特定单元格的值。
*
* @param name 表的名称。
* @param rowKey 行键。
* @param columnFamily 列族。
* @param columnName 列名。
* @throws IOException 如果发生IO异常。
*/
public void selectByGet(String name, String rowKey, String columnFamily, String columnName) throws IOException {
Get get = new Get(Bytes.toBytes(rowKey));
Result result = getTable(name).get(get);
byte[] value = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(columnName));
System.out.println("Value = " + Bytes.toString(value));
}
/**
* 根据行键、列族和列名,以及最大版本数获取单元格的值。
*
* @param name 表的名称。
* @param rowKey 行键。
* @param columnFamily 列族。
* @param columnName 列名。
* @param maxVersion 最大版本数。
* @throws IOException 如果发生IO异常。
*/
public void selectBycell(String name, String rowKey, String columnFamily, String columnName,int maxVersion) throws IOException {
Get get = new Get(Bytes.toBytes(rowKey));
try {
get.setMaxVersions(maxVersion);
} catch (IOException e) {
throw new RuntimeException(e);
}
Result result = getTable(name).get(get);
List
for(Cell cell : cells){
byte[] cvalue = CellUtil.cloneValue(cell);
System.out.println("Value = " + Bytes.toString(cvalue));
}
}
/**
* 根据行键获取整行数据。
*
* @param name 表的名称。
* @param rowKey 行键。
* @throws IOException 如果发生IO异常。
*/
public void selectByRow(String name, String rowKey) throws IOException {
Get get = new Get(Bytes.toBytes(rowKey));
Result result = getTable(name).get(get);
for(Cell cell : result.rawCells()){
System.out.println("Row = " + Bytes.toString(CellUtil.cloneRow(cell)));
System.out.println("Family = " + Bytes.toString(CellUtil.cloneFamily(cell)));
System.out.println("Column = " + Bytes.toString(CellUtil.cloneQualifier(cell)));
System.out.println("Value = " + Bytes.toString(CellUtil.cloneValue(cell)));
System.out.println("Timestamp = " + cell.getTimestamp());
System.out.println("----------------------------------------");
}
}
/**
* 清空表中的所有数据。
*
* @param name 表的名称。
*/
public void truncateTable(String name) {
getAdmin();
TableName tableName = TableName.valueOf(name);
try {
admin.disableTable(tableName);
admin.truncateTable(tableName, false);
} catch (IOException e) {
System.out.println("清空表数据失败");
throw new RuntimeException(e);
}
System.out.println("清空表数据成功");
}
/**
* 删除指定命名空间下的表格。
*
* @param tableName 表格的名称。
* @throws IOException 如果在删除过程中遇到IO异常。
*/
public void deleteTable(String tableName) throws IOException {
// 1. 建立连接
getAdmin();
// 2. 调用方法删除表格
TableName tableName1 = TableName.valueOf(tableName);
if (admin.tableExists(tableName1)) {
admin.disableTable(tableName1);
admin.deleteTable(tableName1);
System.out.println("Table " + tableName + " is deleted.");
}else System.out.println("Table " + tableName + " does not exist.");
}
}
2.3.3 HbaseTest.java
最后这个,和前面创建的类不一样,这是一个测试类,我们在之前创建项目时看见,项目除了有main.java还有个test.java,这个test.java 是专门用来测试的,我们要将HbaseTest.java放在 test.java下面。
我们知道,java代码想要run起来必须要有**main**函数,一个两个测试还好,测试项目多起来,通过main,就会特别麻烦,main会越来越多,或者main里面的代码,注释掉的代码也会越来越多。所以我们要用junit这个包来完成简单的测试。
他的使用方法很简单,在我们写好的方法头上加上 @Test 就可以单独运行这个方法了
import org.example.HBaseCRUD;
import org.junit.Test;
import java.io.IOException;
/**
* HbaseTest 类用于通过 JUnit 测试 HBase 数据库的 CRUD(创建、读取、更新、删除)操作。
*/
public class HbaseTest {
// HBase 表名称
String name = "kpl";
// 行键
String rowkey = "0001";
// 列族名称
String columnfamily = "role";
// 属性名称
String attr_name = "name";
String attr_type = "type";
String attr_duty = "duty";
// 属性值
String value_name = "Hanxin";
String value_type = "Warrior";
String value_duty = "Wild";
// 列族名称数组
String[] familyNames = {"role", "attack", "defence"};
// 时间戳
long timeStamp = 5;
/**
* 测试创建 HBase 表。
* @throws IOException 如果创建表时发生 I/O 错误。
*/
@Test
public void testCreateHbase(){
HBaseCRUD hBaseCRUD = new HBaseCRUD();
try {
hBaseCRUD.createTable(name, familyNames);
} catch (IOException e) {
System.out.println("创建表失败");
throw new RuntimeException(e);
}
}
/**
* 测试向 HBase 表中插入数据。
* @throws IOException 如果插入数据时发生 I/O 错误。
*/
@Test
public void testInsertHbase(){
HBaseCRUD hBaseCRUD = new HBaseCRUD();
try {
// 插入属性值
hBaseCRUD.insertAndModify(name, rowkey, columnfamily, attr_name, timeStamp, value_name);
hBaseCRUD.insertAndModify(name, rowkey, columnfamily, attr_type, timeStamp, value_type);
hBaseCRUD.insertAndModify(name, rowkey, columnfamily, attr_duty, timeStamp, value_duty);
} catch (IOException e) {
throw new RuntimeException(e);
}
System.out.println("插入数据成功");
}
/**
* 测试通过 Get 和 Row 键选择数据。
* @throws IOException 如果选择数据时发生 I/O 错误。
*/
@Test
public void testSelectByGet(){
HBaseCRUD hBaseCRUD = new HBaseCRUD();
try {
// 通过 Get 方式选择数据
hBaseCRUD.selectByGet(name, rowkey, columnfamily, attr_name);
// 通过 Row 键选择数据
hBaseCRUD.selectByRow(name, rowkey);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 测试清空 HBase 表数据。
*/
@Test
public void testTuncateHbase(){
HBaseCRUD hBaseCRUD = new HBaseCRUD();
hBaseCRUD.truncateTable(name);
}
/**
* 测试删除 HBase 表数据。
*/
@Test
public void testdeleteHbase() throws IOException {
HBaseCRUD hBaseCRUD = new HBaseCRUD();
hBaseCRUD.deleteTable(name);
}
}
三.代码测试
使用FinalShell 远程连接 Ubuntu 启动hbase,查看jps。
没有问题后,启动hbase shell,使用list命令查看 hbase中的表。这时候还是什么都没有。
使用HbaseTest.java中的 testCreateHbase方法先测试连接hbase并创建表“kpl”。运行成功后再看hbase shell 使用 list 查看,“kpl”也是创建成功了。
接下来就是测试 testInsertHbase方法,往“kpl”表里面插入准备好的数据,也一样成功了。
测试 testSelectByGet方法 ,通过Get 和 Row 键查询数据,也是没有问题。 testTuncateHbase方法他是要来清除表中数据的。运行后,scan “kpl”,里面就没有数据了
最后一个 testdeleteHbase删除表,运行成功后, “kpl”表也就被删除了。
好文链接
发表评论