实践二 HBase Java API 编程
为什么可以写命令还要编写程序?自动化批量处理?
尽管我们可以通过HBase的shell命令行工具进行数据操作,但在实际的生产环境中,为了提高效率和实现自动化处理,我们通常需要编写程序来与HBase进行交互。
本实例使用Eclipse编写java程序,来对HBase数据库进行增删改查等操作,Eclipse可以在Ubuntu软件中心搜索下载并安装。
第一步:启动hadoop,启动hbase
在开始之前,确保你已经安装了Hadoop和HBase,并且它们正在运行。你可以通过以下命令启动它们:
- cd /usr/local/hadoop
- ./sbin/start-dfs.sh
- cd /usr/local/hbase
- ./bin/start-hbase.sh
HBase 命令要在HBase shell中使用:
启动 HBase shell: 在命令行中输入以下命令来启动 HBase shell:
bash
hbase shell
如果 HBase 服务启动成功,你将看到 HBase shell 的提示符,通常是一个光标后面跟着 hbase>
。
HBase命令使用:使用scan 'Score',示例:
:因为我们表还没被创建,报错Unknown table Score是正常的。
报错了可能因为少了:ssh localhost
这个命令可不能少!使用SSH登录本地主机,确保HBase Shell可以正常访问。
第二步,新建Java Project------>新建Class
第三步:在工程中导入外部jar包:
首先导入前面的HDFS API相应类包(实践一中导入的)。
然后 导入 hbase 安装目录中的 lib 文件中的所有 jar 包。
下列代码包含了数据库创建、增删改查等一系列操作,需要大家根据需要逐步开放注释,进行分阶段运行。
这里给出一个编程实例,,以下是源代码:
-
import org.apache.hadoop.conf.Configuration;
-
import org.apache.hadoop.hbase.*;
-
import org.apache.hadoop.hbase.client.*;
-
import java.io.IOException;
-
public class ExampleForHbase{
-
public static Configuration configuration;
-
public static Connection connection;
-
public static Admin admin;
-
//主函数中的语句请逐句执行,只需删除其前的//即可,如:执行insertRow时请将其他语句注释
-
public static void main(String[] args)throws IOException{
-
//创建一个表,表名为Score,列族为sname,course
-
createTable("Score",new String[]{"sname","course"});
-
//在Score表中插入一条数据,其行键为95001,sname为Mary(因为sname列族下没有子列所以第四个参数为空)
-
//等价命令:put 'Score','95001','sname','Mary'
-
//insertRow("Score", "95001", "sname", "", "Mary");
-
//在Score表中插入一条数据,其行键为95001,course:Math为88(course为列族,Math为course下的子列)
-
//等价命令:put 'Score','95001','score:Math','88'
-
//insertRow("Score", "95001", "course", "Math", "88");
-
//在Score表中插入一条数据,其行键为95001,course:English为85(course为列族,English为course下的子列)
-
//等价命令:put 'Score','95001','score:English','85'
-
//insertRow("Score", "95001", "course", "English", "85");
-
//1、删除Score表中指定列数据,其行键为95001,列族为course,列为Math
-
//执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码取消注释注释,将删除制定列族的代码注释
-
//等价命令:delete 'Score','95001','score:Math'
-
//deleteRow("Score", "95001", "course", "Math");
-
//2、删除Score表中指定列族数据,其行键为95001,列族为course(95001的Math和English的值都会被删除)
-
//执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码注释,将删除制定列族的代码取消注释
-
//等价命令:delete 'Score','95001','score'
-
//deleteRow("Score", "95001", "course", "");
-
//3、删除Score表中指定行数据,其行键为95001
-
//执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码注释,以及将删除制定列族的代码注释
-
//等价命令:deleteall 'Score','95001'
-
//deleteRow("Score", "95001", "", "");
-
//查询Score表中,行键为95001,列族为course,列为Math的值
-
//getData("Score", "95001", "course", "Math");
-
//查询Score表中,行键为95001,列族为sname的值(因为sname列族下没有子列所以第四个参数为空)
-
//getData("Score", "95001", "sname", "");
-
//删除Score表
-
//deleteTable("Score");
-
}
-
//建立连接
-
public static void init(){
-
configuration = HBaseConfiguration.create();
-
configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
-
try{
-
connection= ConnectionFactory.createConnection(configuration);
-
admin = connection.getAdmin();
-
}catch (IOException e){
-
e.printStackTrace();
-
}
-
}
-
//关闭连接
-
public static void close(){
-
try{
-
if(admin != null){
-
admin.close();
-
}
-
if(null != connection){
-
connection.close();
-
}
-
}catch (IOException e){
-
e.printStackTrace();
-
}
-
}
-
/**
-
* 建表。HBase的表中会有一个系统默认的属性作为主键,主键无需自行创建,默认为put命令操作中表名后第一个数据,因此此处无需创建id列
-
* @param myTableName 表名
-
* @param colFamily 列族名
-
* @throws IOException
-
*/
-
public static void createTable(String myTableName,String[] colFamily) throws IOException {
-
init();
-
TableName tableName = TableName.valueOf(myTableName);
-
if(admin.tableExists(tableName)){
-
System.out.println("talbe is exists!");
-
}else {
-
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
-
for(String str:colFamily){
-
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
-
hTableDescriptor.addFamily(hColumnDescriptor);
-
}
-
admin.createTable(hTableDescriptor);
-
System.out.println("create table success");
-
}
-
close();
-
}
-
/**
-
* 删除指定表
-
* @param tableName 表名
-
* @throws IOException
-
*/
-
public static void deleteTable(String tableName) throws IOException {
-
init();
-
TableName tn = TableName.valueOf(tableName);
-
if (admin.tableExists(tn)) {
-
admin.disableTable(tn);
-
admin.deleteTable(tn);
-
}
-
close();
-
}
-
/**
-
* 查看已有表
-
* @throws IOException
-
*/
-
public static void listTables() throws IOException {
-
init();
-
HTableDescriptor hTableDescriptors[] = admin.listTables();
-
for(HTableDescriptor hTableDescriptor :hTableDescriptors){
-
System.out.println(hTableDescriptor.getNameAsString());
-
}
-
close();
-
}
-
/**
-
* 向某一行的某一列插入数据
-
* @param tableName 表名
-
* @param rowKey 行键
-
* @param colFamily 列族名
-
* @param col 列名(如果其列族下没有子列,此参数可为空)
-
* @param val 值
-
* @throws IOException
-
*/
-
public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException {
-
init();
-
Table table = connection.getTable(TableName.valueOf(tableName));
-
Put put = new Put(rowKey.getBytes());
-
put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes());
-
table.put(put);
-
table.close();
-
close();
-
}
-
/**
-
* 删除数据
-
* @param tableName 表名
-
* @param rowKey 行键
-
* @param colFamily 列族名
-
* @param col 列名
-
* @throws IOException
-
*/
-
public static void deleteRow(String tableName,String rowKey,String colFamily,String col) throws IOException {
-
init();
-
Table table = connection.getTable(TableName.valueOf(tableName));
-
Delete delete = new Delete(rowKey.getBytes());
-
//删除指定列族的所有数据
-
//delete.addFamily(colFamily.getBytes());
-
//删除指定列的数据
-
//delete.addColumn(colFamily.getBytes(), col.getBytes());
这里应该是:
if (col != null && !col.isEmpty()) {
// 如果有 col 参数传入,则删除指定列
delete.addColumn(colFamily.getBytes(), col.getBytes());
} else if(colFamily != null && !colFamily.isEmpty()) {
// 否则,删除指定列族的所有数据
delete.addFamily(colFamily.getBytes());
}
- table.delete(delete);
- table.close();
- close();
- }
- /**
- * 根据行键rowkey查找数据
- * @param tableName 表名
- * @param rowKey 行键
- * @param colFamily 列族名
- * @param col 列名
- * @throws IOException
- */
- public static void getData(String tableName,String rowKey,String colFamily,String col)throws IOException{
- init();
- Table table = connection.getTable(TableName.valueOf(tableName));
- Get get = new Get(rowKey.getBytes());
- get.addColumn(colFamily.getBytes(),col.getBytes());
- Result result = table.get(get);
- showCell(result);
- table.close();
- close();
- }
- /**
- * 格式化输出
- * @param result
- */
- public static void showCell(Result result){
- Cell[] cells = result.rawCells();
- for(Cell cell:cells){
- System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" ");
- System.out.println("Timetamp:"+cell.getTimestamp()+" ");
- System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" ");
- System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" ");
- System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" ");
- }
- }
- }
第四步:执行与验证
每次执行完,都可以回到 shell 界面查看是否执行成功 ,如:执行完插入数据后,在shell界面中执行scan 'Score'。截图如下:
建表:
建表成功~
添加数据:
删除指定列:
删除指定列族:
删除整行数据:
查询Score表中,行键为95001,列族为course,列为Math的值:
查询Score表中,行键为95001,列族为sname的值(因为sname列族下没有子列所以第四个参数为空):
【遇到的问题】:为什么打印了内存地址而不是值?
【解决方法】:把+" "删除就好了?