直接上代码如下:
package com.hbase.demo;
/**
* Hbase 版本号:1.2.4
*/
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
public class HBaseTest {
public static Configuration conf = null;
public static Admin admin;
public static Connection connection;
public static Table table;
static {
try {
conf = HBaseConfiguration.create();
connection = ConnectionFactory.createConnection(conf);
// -----这两个在hbase-site.xml的配置文件中配置好便不需要在这里进行重新配置了
// conf.set("hbase.zookeeper.quorum", "centosm");
// conf.set("hbase.rootdir", "hdfs://centosm:9000/hbase");
admin = connection.getAdmin();
} catch (IOException e) {
e.printStackTrace();
}
}
// 关闭连接
public static void close() {
try {
if (admin != null) {
admin.close();
}
if (null != connection) {
connection.close();
}
if (table != null){
table.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 创建一张表
* @param myTableName
* @param colFamily
* @param deleteFlag true:存在则删除再重建
* @throws Exception
*/
public static void creatTable(String myTableName, String[] colFamily, boolean deleteFlag) throws Exception {
TableName tableName = TableName.valueOf(myTableName);
if (admin.tableExists(tableName)) {
if (!deleteFlag) {
System.out.println(myTableName + " table exists!");
} else {
HBaseTest.deleteTable(myTableName); // 先删除原先的表
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
for (String str : colFamily) {
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
hTableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(hTableDescriptor);
System.out.println(myTableName + "表创建成功。。。");
}
} else {
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
for (String str : colFamily) {
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
hTableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(hTableDescriptor);
System.out.println(myTableName + "表创建成功。。。");
}
//close();
}
/**
* 往表中添加数据(单条添加)
*/
public static void inserData(String myTableName, String rowKey, String colFamily, String col, String val) {
try {
table = connection.getTable(TableName.valueOf(myTableName));
Put put = new Put(Bytes.toBytes(rowKey));
put.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(col), Bytes.toBytes(val));
table.put(put);
System.out.println("数据插入成功。。。rowkey为:" + rowKey);
} catch (IOException e) {
e.printStackTrace();
} finally {
//close();
}
}
/**
* 往表中批量添加数据
*/
public static void batchInserData(String myTableName, String colFamily, String col, int insertNum) {
try {
table = connection.getTable(TableName.valueOf(myTableName));
List<Put> list = new ArrayList<Put>();
Put put;
for (int i = 0; i < insertNum; i++) {
put = new Put(Bytes.toBytes("rowKey" + i));
put.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(col), Bytes.toBytes("110804" + i));
list.add(put);
}
table.put(list);
System.out.println("数据插入成功。。。");
} catch (IOException e) {
e.printStackTrace();
} finally {
// close();
}
}
/**
* 获取数据(根据行键获取其整行数据)
*/
public static void getDataFromRowKey(String myTableName, String rowKey) {
try {
table = connection.getTable(TableName.valueOf(myTableName));
Get get = new Get(Bytes.toBytes(rowKey));
Result re = table.get(get);
List<Cell> listCells = re.listCells();
for (Cell cell : listCells) {
System.out.println(new String(CellUtil.cloneRow(cell)) + "\t" + new String(CellUtil.cloneFamily(cell))
+ "\t" + new String(CellUtil.cloneQualifier(cell)) + "\t"
+ new String(CellUtil.cloneValue(cell)) + "\t" + cell.getTimestamp());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//close();
}
}
/**
* 根据表名与行键及列簇获取数据
* @param myTableName
* @param rowKey
* @param colFamily
* @param Col
* @throws IOException
*/
private static void getData(String myTableName, String rowKey, String colFamily, String col) throws IOException {
table = connection.getTable(TableName.valueOf(myTableName));
Get get = new Get(Bytes.toBytes(rowKey));
get.addColumn(Bytes.toBytes(colFamily), Bytes.toBytes(col));
Result re = table.get(get);
if (re.isEmpty()){
System.out.println("查询结果为空。。。。");
return;
}
List<Cell> listCells = re.listCells();
for (Cell cell : listCells) {
System.out.println(new String(CellUtil.cloneRow(cell)) + "\t" + new String(CellUtil.cloneFamily(cell))
+ "\t" + new String(CellUtil.cloneQualifier(cell)) + "\t"
+ new String(CellUtil.cloneValue(cell)) + "\t" + cell.getTimestamp());
}
// close();
}
/**
* 根据表名查询整张表的数据(当然同样可根据列簇,列分割符等进行scan的查询,这里不进行细写了)
* @param tablename
* @throws IOException
*/
private static void getScanData(String tablename) throws IOException {
table = connection.getTable(TableName.valueOf(tablename));
ResultScanner scanner = table.getScanner(new Scan());
Iterator<Result> it = scanner.iterator();
while(it.hasNext()) {
Result re = it.next();
List<Cell> listCells = re.listCells();
for (Cell cell : listCells) {
System.out.println(new String(CellUtil.cloneRow(cell)) + "\t" + new String(CellUtil.cloneFamily(cell))
+ "\t" + new String(CellUtil.cloneQualifier(cell)) + "\t"
+ new String(CellUtil.cloneValue(cell)) + "\t" + cell.getTimestamp());
}
}
}
/**
* 删除数据
* @param tableName
* @param rowKey
* @throws IOException
*/
private static void delDByRowKey(String tableName, String rowKey) {
try {
table = connection.getTable(TableName.valueOf(tableName));
Delete delete = new Delete(Bytes.toBytes(rowKey));
table.delete(delete);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(tableName + " 表中rowKey为 " + rowKey + " 的数据已被删除....");
}
/**
* 删除一张表
*
* @param args
*/
public static void deleteTable(String myTableName) {
try {
TableName tableName = TableName.valueOf(myTableName);
admin.disableTable(tableName); // 删除表前先对表进行disable
admin.deleteTable(tableName);
System.out.println(tableName + " 表已被删除。。。");
} catch (IOException e) {
e.printStackTrace();
} finally {
close();
}
}
/**
* 删除列簇
*
* @param args
*/
public static void deleteColumnFamily(String myTableName, byte[] colFamily) {
try {
TableName tableName = TableName.valueOf(myTableName);
admin.disableTable(tableName); // 删除前先对表进行disable
admin.deleteColumn(tableName, colFamily);
System.out.println(tableName + " 表 " + colFamily + " 列已被删除。。。");
} catch (IOException e) {
e.printStackTrace();
} finally {
close();
}
}
public static void main(String[] args) {
try {
// 创建表
String tablename = "student";
// String[] familys = { "grade","course" };
// boolean booleanFlog = true;
// HBaseTest.creatTable(tablename, familys, booleanFlog);
//
// /**
// * 往表中插入数据:插入数据的时候指定数据所属的列簇与列分割符
// */
//
// String rowKey = "ycb";
// String colFamily = "course";
// String col = "English";
// String val = "88";
//
// String rowKey2 = "hehe";
// String val2 = "89";
//
// HBaseTest.inserData(tablename, rowKey, colFamily, col, val);
// HBaseTest.inserData(tablename, rowKey2, colFamily, col, val2);
//
//
// /**
// * 根据表名与行键查询整行数据
// */
//
// HBaseTest.getDataFromRowKey(tablename, rowKey);
// HBaseTest.getDataFromRowKey(tablename, rowKey2);
//
//
// /**
// * 根据表名与行键及列簇获取数据
// */
// colFamily = "course";
// col = "English";
// HBaseTest.getData(tablename, rowKey, colFamily, col);
// /**
// * 查询整张表的数据
// */
// HBaseTest.getScanData(tablename);
//
// /**
// * 根据rowkey删除指定数据
// */
// String rowKey = "ycb";
// HBaseTest.delDByRowKey(tablename, rowKey);
// /**
// * 批量插入数据
// */
// String colFamily = "grade";
// String col = "sid";
// int inserNum = 10;
// HBaseTest.batchInserData(tablename, colFamily, col, inserNum);
//
// /**
// * 删除列簇
// */
// /*
// * String tablename = "scores3";
// * byte[] colFamily = Bytes.toBytes("course");
// * HBaseTest.deleteColumnFamily(tablename, colFamily);
// */
// /**
// * 删除表
// */
// String tablename = "scores";
// HBaseTest.deleteTable(tablename);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Hbase 在Eclipse中环境的搭建步骤如下:
一、前提环境:
特别注意:在win系统下将集群主机名与ip地址写到hosts中
路径:C:\Windows\System32\drivers\etc 下的HOSTS文件
如下将集群的ip与主机名追加到win 的 HOSTS文件
192.168.2.125 centosm
在虚拟机中搭建的伪分布集群,主机名为centosm
启动hadoop与hbase
在浏览器中访问hbase看否启动成功
地址如下:http://centosm:16010/master-status
二、开始调在Eclipse中调用Hbase的Api
1、在eclipse里新建一个Java项目HBaseDemo,由于只是测试,就简单一点,将所有的集群中Hbase Lib 目录下的JAR选上都放到Java项目中。
2、在项目HBaseDemo 下增加一个文件夹conf,将Hbase集群的配置文件hbase-site.xml复制到该目录,然后选择项目属性在Libraries->Add Class Folder,将刚刚增加的conf目录选上。
hbase-site.xml
<configuration>
<property>
<name>hbase.rootdir</name>
<!-- <value>file:///home/centosm/hbase/data</value> -->
<value>hdfs://centosm:9000/hbase</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>centosm</value>
</property>
</configuration>
3、完成上述便可以像普通项目开发了(笔者的集群是在linux下搭建的伪分布集群,Eclipse是在win10下的)
==============================================
在开发过程遇到的一些小问题及解决方法
1、运行程序时输入如下错误:
org.apache.hadoop.hbase.client.RetriesExhaustedException
Caused by: java.net.UnknownHostException: centosm
解决:
如下将集群的ip与主机名追加到win 的 HOSTS文件
192.168.2.125 centosm
2、在linux中运行时出现如下错:
hbase(main):002:0> list
TABLE
ERROR: org.apache.hadoop.hbase.ipc.ServerNotRunningYetException: Server is not running yet
at org.apache.hadoop.hbase.master.HMaster.checkServiceStarted(HMaster.java:2286)
at org.apache.hadoop.hbase.master.MasterRpcServices.isMasterRunning(MasterRpcServices.java:931)
at org.apache.hadoop.hbase.protobuf.generated.MasterProtos$MasterService$2.callBlockingMethod(MasterProtos.java:55654)
at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2180)
at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:112)
at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:133)
at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:108)
at java.lang.Thread.run(Thread.java:745)
Here is some help for this command:
List all tables in hbase. Optional regular expression parameter could
be used to filter the output. Examples:
hbase> list
hbase> list 'abc.*'
hbase> list 'ns:abc.*'
hbase> list 'ns:.*'
解决:hdfs dfsadmin -safemode leave 退出安全模式
查看安全模式状态相关的命令如下:
[centosm@centosm ~]$ hdfs dfsadmin -safemode get
Safe mode is ON
[centosm@centosm ~]$ hdfs dfsadmin -safemode leave
Safe mode is OFF
[centosm@centosm ~]$ hdfs dfsadmin -safemode enter
Safe mode is ON
[centosm@centosm ~]$ hdfs dfsadmin -safemode leave
Safe mode is OFF
[centosm@centosm ~]$ hdfs dfsadmin -safemode get
Safe mode is OFF
3、
hbase(main):002:0> list 出现下列错误
ERROR: Can't get master address from ZooKeeper; znode data == null
Here is some help for this command:
List all tables in hbase. Optional regular expression parameter could
be used to filter the output. Examples:
出现此问题可能是zookeeper不稳定造成的,采用的是虚拟机,经常挂起的状态,使用Hbase的list命令出现下面错误,这个可能是hbase的稳定性造成的,解决办法有两种。这里使用第一种办法就解决了。
解决方法:
方法1.重启hbase
问题解决。
方法2:格式化namenode
将namenode的信息删除,重新格式化
重新启动,hbase正常
4、在Eclipse 运行程序出现的错误
ERROR org.apache.hadoop.hbase.client.AsyncProcess - Failed to get region location
java.io.IOException: Failed to get result within timeout, timeout=60000ms
at org.apache.hadoop.hbase.client.ScannerCallableWithReplicas.call(ScannerCallableWithReplicas.java:206)
at org.apache.hadoop.hbase.client.ScannerCallableWithReplicas.call(ScannerCallableWithReplicas.java:60)
at org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithoutRetries(RpcRetryingCaller.java:210)
笔者在虚拟机上搭了一个hadoop伪分布式的环境,在虚拟服务器上 /etc/hosts 配置如下:
[centosm@centosm ~]$ more /etc/hosts
192.168.0.108 centosm
192.168.22.125 centosm
在win10 中的hosts方件最后加像linux中的添加了这两个地址,如下所示:
192.168.22.125 centosm
192.168.0.108 centosm
注意:因为笔者的在公司环境与在家里的环境的ip地址不一样,所以上面不同 ip 地址对应的主机名是一样的,这样配置在linux环境中是没有任何问题的,但是win10是支持这么配置的。
解决方式:暂时将win10上用不上的ip与主机名注释掉便可。