基本原理介绍:
1.Java客户端其实就是shell客户端的一种实现,操作命令基本上就是shell客户端命令的一个映射。
2.Java客户端使用的配置信息是被映射到了HbaseConfiguration的实例对象中的,使用HBaseConfiguration.create()
方法创建实例化对象的时候,会从classpath中获取hbase-site.xml
文件并进行配置文件内容的读取。同时也会读取hadoop的配置文件
信息。这里我们给定zookeeper的相关配置信息即可。
3.流程:先通过zookeeper拿到hbase:namespace的路径,然后从这个路径中拿到hbase:meta表的信息,接着就拿到了用户表的路径
——摘自kevin&learn
前提条件
- 本地Windows(7或10)系统下已经装好了JDK和Eclipse,笔者电脑JDK1.8。
- 已经有搭建好的完全分布式集群,并已经成功启动Hadoop,Zookeeper和HBase。笔者当前搭建好的集群是
Hadoop-3.0.3
,Zookeeper-3.4.13
和HBase-2.1.0
。 - 本地已经成功连接到远程HBase,连接方法详见:《本地Java连接远程集群上的HBase》
Hostname | IP |
---|---|
master | 10.0.86.245 |
ceph1 | 10.0.86.246 |
ceph2 | 10.0.86.221 |
ceph3 | 10.0.86.253 |
以下先逐个讲解每个操作的方法,文章最后附完整代码。
前言:建立连接和关闭连接
1.需要三个静态属性
public static Configuration configuration; //配置对象,用于管理配置信息(类似hbase-site.xml)
public static Connection connection; //连接对象,用于连接数据库
public static Admin admin; //管理对象,用于管理表(如对表的增删改查)
2.创建连接(初始化)
public static void init(){
//1.根据hbase-site.xml文件初始化Configuration对象
configuration = HBaseConfiguration.create();
configuration.set("hbase.rootdir","hdfs://master:9000/hbase");
configuration.set("hbase.zookeeper.quorum", "master,ceph1,ceph2,ceph3");
configuration.set("hbase.zookeeper.property.clientPort", "2181");
try{
//2.根据Configuration对象初始化Connection对象
connection = ConnectionFactory.createConnection(configuration);
//3.根据Connection对象获取Admin对象
admin = connection.getAdmin();
System.out.println("连接HBase成功.");
}catch (IOException e){
System.err.println("连接HBase失败.");
}
}
连接是否成功的关键代码是:
connection = ConnectionFactory.createConnection(configuration);
3.关闭连接
实际就是close掉admin
和connection
。
public static void close(){
try{
if(admin != null){
admin.close();
}
if(null != connection){
connection.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
一、创建数据库表
查询新的API文档发现官网确实要在3.x版本中废弃1.x用的类和部分方法,遂笔者换了一个新的类和方法实现创建表功能。(注:以下为测试每个方法,所以在方法的开头结尾加上了数据库的创建连接和关闭连接,实际应用中无需这样)
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 { //若要创建的表名不存在,则创建新表
TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(tableName); //创建新表实例
for(String str:colFamily){
ColumnFamilyDescriptor columnfamily = ColumnFamilyDescriptorBuilder.of(str); //根据字符串列簇名分别创建新的列簇
tableDescriptor.setColumnFamily(columnfamily); //把新列簇依次添加到新表实例中
}
admin.createTable(tableDescriptor.build()); //把创建的新表实例添加到HBase中
System.out.println("create table success");
}
close(); //关闭连接
}
示例:创建一个名字为ls_world
表,列簇分别为w1
,w2
。
$ create 'ls_world','w1','w2'
createTable("ls_world",new String[]{"w1","w2"});
在HBase shell或http://10.0.86.245:16010可看到
补充解释:
1.从HBase API上可以看到,newBuilder
方法返回的是TableDescriptorBuilder
,所以最后填入admin.createTable(tableDescriptor.build());
方法中加了build()
方法以保证返回类型是TableDescriptor
。
TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(tableName);
2.从HBase API上可以看到,ColumnFamilyDescriptorBuilder
对象可以调用of()
方法,填入字符串参数即可返回ColumnFamilyDescriptor
对象,可直接传入setColumnFamily()
方法。
ColumnFamilyDescriptor columnfamily = ColumnFamilyDescriptorBuilder.of(str);
二、删除数据库表
和直接在HBase shell操作一样,需要先disable
,再delete
。
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();
}
示例:删除一个名字为Score
表。
$ disable 'Score'
$ drop 'Score'
deleteTable("Score");
三、向某行某列插入数据
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实例,添加rowKey参数
put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes()); //添加其余参数
table.put(put); //插入到表中
table.close();
close();
}
示例:向ls_world
表的w1
列簇中插入以下数据。
$ put 'ls_world','95001','w1:name','Jack'
insertRow("ls_world", "95001", "w1", "name", "Jack");
四、删除表中数据
删除指定列簇和指定列的数据
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());
if(col.equals("")) //删除指定列族的所有数据
delete.addFamily(colFamily.getBytes());
else //删除指定列的数据
delete.addColumn(colFamily.getBytes(), col.getBytes());
table.delete(delete);
table.close();
close();
}
示例:删除ls_world
表的w1
列簇中age
列数据,或w1
列簇中所有数据数据。
$ delete 'ls_world','95001','w1:age'
$ delete 'ls_world','95001','w1'
deleteRow("ls_world", "95001", "w1", "age");
deleteRow("ls_world", "95001", "w1", "");
五、根据行键rowkey查找数据
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());
if(col.equals(""))
get.addFamily(colFamily.getBytes());
else
get.addColumn(colFamily.getBytes(),col.getBytes());
Result result = table.get(get);
showCell(result); //格式化输出
table.close();
close();
}
public static void showCell(Result result){ //格式化输出
Cell[] cells = result.rawCells();
for(Cell cell:cells){
System.out.println(new String(CellUtil.cloneFamily(cell))+":"
+new String(CellUtil.cloneQualifier(cell))
+" timestamp="
+cell.getTimestamp()+", value="
+new String(CellUtil.cloneValue(cell)));
}
}
示例:查询ls_world
表95001
行的w1
列簇中所有数据,或w1
列簇中age
列数据。
$ get 'ls_world','95001','w1'
$ get 'ls_world','95001','w1:age'
getData("ls_world", "95001", "w1", "");
getData("ls_world", "95001", "w1", "age");
查询结果如下:
对照HBase shell中的查询结果相同。
六、列出当前所有数据库表
public static void listTables() throws IOException {
init();
TableName tablenames[] = admin.listTableNames();
for(TableName tablename:tablenames){
System.out.println(tablename.getNameAsString());
}
close();
}
示例:列出当前所有数据库表。
$ list 'ls_world'
listTables()
查询结果如下:
对照HBase shell中的查询结果相同。
完整代码如下
package test1;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import java.io.IOException;
public class testOne{
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
public static void main(String[] args)throws IOException{
//init();
//close();
//createTable("ls_world",new String[]{"w1","w2"});
//insertRow("ls_world", "95001", "w2", "age", "22");
//insertRow("ls_world", "95001", "w2", "friend", "eeeea");
//deleteTable("Score");
//deleteRow("ls_world", "95001", "w1", "");
//getData("ls_world", "95001", "w1", "age");
listTables();
}
//建立连接
public static void init(){
// 根据 hbase-site.xml 文件初始化 Configuration 对象
configuration = HBaseConfiguration.create();
configuration.set("hbase.rootdir","hdfs://master:9000/hbase");
configuration.set("hbase.zookeeper.quorum", "master,ceph1,ceph2,ceph3");
configuration.set("hbase.zookeeper.property.clientPort", "2181");
try{
// 根据 Configuration 对象初始化 Connection 对象
connection = ConnectionFactory.createConnection(configuration);
admin = connection.getAdmin();
System.out.println("连接HBase成功.");
}catch (IOException e){
System.err.println("连接HBase失败.");
}
}
//关闭连接
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 {
TableDescriptorBuilder tableDescriptor = TableDescriptorBuilder.newBuilder(tableName);
for(String str:colFamily){
ColumnFamilyDescriptor columnfamily = ColumnFamilyDescriptorBuilder.of(str);
tableDescriptor.setColumnFamily(columnfamily);
}
admin.createTable(tableDescriptor.build());
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();
TableName tablenames[] = admin.listTableNames();
for(TableName tablename:tablenames){
System.out.println(tablename.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());
if(col.equals("")) //删除指定列族的所有数据
delete.addFamily(colFamily.getBytes());
else //删除指定列的数据
delete.addColumn(colFamily.getBytes(), col.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());
if(col.equals(""))
get.addFamily(colFamily.getBytes());
else
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(new String(CellUtil.cloneFamily(cell))+":"
+new String(CellUtil.cloneQualifier(cell))
+" timestamp="
+cell.getTimestamp()+", value="
+new String(CellUtil.cloneValue(cell)));
}
}
}