10.4.20.49 Master
10.4.20.67 Slave1
10.4.20.69 Slave2
10.4.20.70 slave3
以上ip和节点名对应我之前搭的hadoop,然后还需要把hbase安装包解压后的lib里的包全部导入到eclipse项目里。
hbase版本为hbase-0.98.23-hadoop2-bin,本文学习内容转载自:【甘道夫】HBase基本数据操作详解【完整版,绝对精品】。
概述:
1.对于建表,和RDBMS类似,HBase也有namespace的概念,可以指定表空间创建表,也可以直接创建表,进入default表空间。2.对于数据操作,HBase支持四类主要的数据操作,四个类都是org.apache.hadoop.hbase.client的子类,分别是:
•Put:增加一行,修改一行;
•Delete:删除一行,删除指定列族,删除指定column的多个版本,删除指定column的指定版本等;
•Get:获取指定行的所有信息,获取指定行和指定列族的所有colunm,获取指定column,获取指定column的几个版本,获取指定column的指定版本等;
•Scan:获取所有行,获取指定行键范围的行,获取从某行开始的几行,获取满足过滤条件的行等。
一、命名空间Namespace
在关系数据库系统中,命名空间namespace指的是一个表的逻辑分组,同一组中的表有类似的用途。命名空间的概念为即将到来的多租户特性打下基础:•配额管理(Quota Management (HBASE-8410)):限制一个namespace可以使用的资源,资源包括region和table等;
•命名空间安全管理(Namespace Security Administration (HBASE-9206)):提供了另一个层面的多租户安全管理;
•Region服务器组(Region server groups (HBASE-6721)):一个命名空间或一张表,可以被固定到一组regionservers上,从而保证了数据隔离性。
1.命名空间管理
Example:hbase shell中创建命名空间、创建命名空间中的表、移除命名空间、修改命名空间:
#Create a namespace2. 预定义的命名空间
create_namespace 'my_ns'
#create my_table in my_ns namespace
create 'my_ns:my_table', 'fam'
#drop namespace
drop_namespace 'my_ns'
#alter namespace
alter_namespace 'my_ns', {METHOD => 'set', 'PROPERTY_NAME' => 'PROPERTY_VALUE'}
有两个系统内置的预定义命名空间:
•hbase:系统命名空间,用于包含hbase的内部表
•default:所有未指定命名空间的表都自动进入该命名空间
Example:指定命名空间和默认命名空间:
#namespace=foo and tableName=bar and columnFamily=cf1命名空间一般在建模阶段通过命令行创建,在java代码中创建的机会不多,就不列出来了,但要注意带命名空间的表名要写为“namespace:tablename”的格式,以下我都是用默认的default命名空间。
create 'foo:bar', 'cf1'
#namespace=default and tableName=bar and columnFamily=cf1
create 'bar', 'cf1'
二、建表create
1.创建HBaseAdmin对象时就已经建立了客户端程序与HBase集群的connection,所以在程序执行完成后,务必通过HBaseAdmin.close()关闭connection;2.可以通过HTableDescriptor对象设置表的特性,比如: 通过HTableDescriptor.setMaxFileSize(512)设置一个region中的store文件的最大size,当一个region中的最大store文件达到这个size时,region就开始分裂; 通过HTableDescriptor.setMemStoreFlushSize(512)设置region内存中的memstore的最大值,当memstore达到这个值时,开始往磁盘中刷数据。
3.可以通过HColumnDescriptor对象设置列族的特性,比如: 通过HColumnDescriptor.setTimeToLive(5184000)设置数据保存的最长时间; 通过HColumnDescriptor.setInMemory(true)设置数据保存在内存中以提高响应速度; 通过 HColumnDescriptor.setMaxVersions(10)设置数据保存的最大版本数; 通过HColumnDescriptor.setMinVersions(5)设置数据保存的最小版本数(配合存活时间TimeToLive使用)。
4.数据的版本数只能通过HColumnDescriptor对象设置,不能通过HTableDescriptor对象设置;
5.由于HBase的数据是先写入内存,数据累计达到内存阈值时才往磁盘中flush数据,所以,如果在数据还没有flush进硬盘时,regionserver down掉了,内存中的数据将丢失。要想解决这个问题就需要用到WAL(Write-Ahead-Log),HTableDescriptor.setDurability(Durability.SYNC_WAL)就是设置写WAL日志的级别,示例中设置的是同步写SYNC,该方式安全性较高,但无疑会一定程度影响性能,请根据具体场景选择使用;
6.setDurability(Durability d)方法可以在相关的三个对象中使用,分别是:HTableDescriptor,Delete,Put(其中Delete和Put的该方法都是继承自父类org.apache.hadoop.hbase.client.Mutation)。分别针对表、插入操作、删除操作设定WAL日志写入级别。需要注意的是,Delete和Put并不会继承Table的Durability级别(已实测验证)。Durability是一个枚举变量,可选值如下:
•ASYNC_WAL : 当数据变动时,异步写WAL日志
•SYNC_WAL : 当数据变动时,同步写WAL日志
•FSYNC_WAL : 当数据变动时,同步写WAL日志,并且,强制将数据写入磁盘
•SKIP_WAL : 不写WAL日志
•USE_DEFAULT : 使用HBase全局默认的WAL写入级别,即SYNC_WAL。
三、修改表结构
以删除和添加某表的列族为例://1.修改之前先使表变为不可用状态:
admin.disableTable("tablename");
//2.取得目标表的描述对象:
HTableDescriptor htd= admin.getTableDescriptor("tablename");
//HColumnDescriptor hcd = htd.getFamily("列族名");
//3.修改目标表描述对象,即删除列族:
htd.removeFamily("列族名");
//4.添加一个新列族:
HColumnDescriptor newhcd = new HColumnDescriptor("列族名");
newhcd.setMaxVersions(10);
newhcd.setKeepDeletedCells(true);//使那些被打上删除标记但尚未被真正删除的数据,在查询时仍然能被查询到
htd.addFamily(newhcd);
//5.将修改后的描述对象应用到目标表:
admin.modifyTable("tablename",htd)
四、新增、更新数据Put
1. 常用构造函数:Put(byte[] rowArray, int rowOffset, int rowLength, long ts)第一个参数为行键rowkey,是必须的,后边三个可选,中间俩是从目标字符串(前边的rowkey)中提取子串作为行键(第一个参数是从第几个字符开始截取,第二个是截取长度),最后一个指定时间戳。
2. 常用方法:•add(byte[] family, byte[] qualifier, long ts, byte[] value) 指定列族、限定符(列)、时间戳,值value
•setDurability(Durability d) 设置写WAL(Write-Ahead-Log)的级别,d的可选项上边写有。
3. Put的构造函数都需要指定行键,如果是全新的行键,则新增一行;如果是已有的行键,则更新现有行。
4. 创建Put对象及put.add过程都是在构建一行的数据,创建Put对象时相当于创建了行对象,add的过程就是往目标行里添加cell,直到table.put才将数据插入表格;
五、获取单行数据Get
1. 构造函数:Get的构造函数很简单,只有一个:Get(byte[] row) 参数是行键。2. 常用方法:
•addFamily(byte[] family) 指定希望获取的列族
•addColumn(byte[] family, byte[] qualifier) 指定希望获取的列
•setTimeRange(long minStamp, long maxStamp) 设置获取数据的时间戳范围
•setTimeStamp(long timestamp) 设置获取数据的指定时间戳
•setMaxVersions(int maxVersions) 设定获取数据的版本数,参数为空的话就获得所有的版本,不写出这个方法的话默认为1。能输出多版本数据的前提是当前列族能保存多版本数据,列族可以保存的数据版本数通过HColumnDescriptor的setMaxVersions(Int)方法设置。
•setCacheBlocks(boolean cacheBlocks) 设置该Get获取的数据是否缓存在内存中
•setFilter(Filter filter) 为Get对象添加过滤器
六、获取多行Scan
1. 常用构造函数:•创建Scan,从指定行开始扫描(如果指定行不存在,从下一个最近的行开始):
Scan(byte[] startRow)参数:startRow行键
•创建Scan,指定起止行(startRow <= 结果集 < stopRow):
Scan(byte[] startRow, byte[] stopRow)参数:startRow起始行,stopRow终止行
•创建Scan,指定起始行和过滤器:
Scan(byte[] startRow, Filter filter) 参数:startRow起始行,filter过滤器
2. 常用方法:
•setStartRow(byte[] startRow) 设置Scan的开始行,默认结果集包含该行。如果希望结果集不包含该行,可以在行键末尾加上0。
•setStopRow(byte[] stopRow) 设置Scan的结束行,默认结果集不包含该行。如果希望结果集包含该行,可以在行键末尾加上0。
•addFamily(byte[] family) 指定扫描的列族
•addColumn(byte[] family, byte[] qualifier) 指定扫描的列
•setTimeRange(long minStamp, long maxStamp) 扫描指定时间范围的数据
•setTimeStamp(long timestamp) 扫描指定时间戳的数据
•setFilter(Filter filter) 为Scan设置过滤器
•setReversed(boolean reversed) 设置Scan的扫描顺序,默认是正向扫描(false),可以设置为逆向扫描(true)。注意:该方法0.98版本以后才可用!!
•setMaxVersions(int maxVersions) 设定获取数据的版本数,参数为空的话就获得所有的版本,不写出这个方法的话最大版本数默认为1。
•setCaching(int caching) Scan的结果数据是可以缓存在内存中的,设定缓存在内存中的行数,缓存得越多,以后查询结果越快,同时也消耗更多内存,可以通过getCaching()方法来查看当前设定的缓存条数,此外,通过setCacheBlocks方法设置是否缓存Scan的结果数据块,默认为true。
•setRaw(boolean raw) 激活或者禁用raw模式。如果raw模式被激活,Scan将返回所有已经被打上删除标记但尚未被真正删除的数据。该功能仅用于激活了KEEP_DELETED_ROWS的列族,即列族开启了hcd.setKeepDeletedCells(true)。Scan激活raw模式后,就不能指定任意的列,否则会报错。
七、Delete删除表或数据
1. 建表或删表都要创建HBaseAdmin,Delete删除表前必须先disable表。2. 删除数据:Delete类用于删除表中的一行数据,通过HTable.delete来执行该动作。在执行Delete操作时,HBase并不会立即删除数据,而是对需要删除的数据打上一个“墓碑”标记,直到当Storefile合并时,再清除这些被标记上“墓碑”的数据。
3. 构造函数:
•指定要删除的行键:
Delete(byte[] row)删除行键指定行的数据。如果没有进一步的操作,使用该构造函数将删除行键指定的行中所有列族中所有列的所有版本!
•指定要删除的行键和时间戳:
Delete(byte[] row, long timestamp)删除行键和时间戳共同确定行的数据。如果没有进一步的操作,使用该构造函数将删除行键指定的行中,所有列族中所有列的时间戳小于等于指定时间戳的数据版本。
注意:该时间戳仅仅和删除行有关,如果需要进一步指定列族或者列,你必须分别为它们指定时间戳。
•给定一个字符串,目标行键的偏移,截取的长度,时间戳:
Delete(byte[] rowArray, int rowOffset, int rowLength, long ts)
4. 常用方法:
•deleteColumn(byte[] family, byte[] qualifier) 删除指定列的最新版本的数据。
•deleteColumns(byte[] family, byte[] qualifier) 删除指定列的所有版本的数据。
•deleteColumn(byte[] family, byte[] qualifier, long timestamp) 删除指定列的指定版本的数据。
•deleteColumns(byte[] family, byte[] qualifier, long timestamp) 删除指定列的,时间戳小于等于给定时间戳的所有版本的数据。
•deleteFamily(byte[] family) 删除指定列族的所有列的所有版本数据。
•deleteFamily(byte[] family, long timestamp) 删除指定列族的所有列中时间戳小于等于指定时间戳的所有数据。
•deleteFamilyVersion(byte[] family, long timestamp) 删除指定列族中所有列的时间戳等于指定时间戳的版本数据。
•setTimestamp(long timestamp) 为Delete对象设置时间戳。
这里单独列出甘道夫的文章中的删除数据的例子: 删除指定列的所有版本:
Configuration conf = HBaseConfiguration.create();然后我们会发现,100003行的整个info:address列都没了:
HTable table = new HTable(conf, "rd_ns:leetable");
Delete delete = new Delete(Bytes.toBytes("100003"));
delete.deleteColumns(Bytes.toBytes("info"), Bytes.toBytes("address"));
table.delete(delete);
table.close();
hbase(main):009:0> scan 'rd_ns:leetable'
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:age, timestamp=1405390959464, value=301
100003 column=info:name, timestamp=1405390959464, value=show1
3 row(s) in 0.0240 seconds
删除指定列族中所有列的时间戳等于指定时间戳的版本数据:
为了演示效果,我已经向100003行的info:address列新插入一条数据
hbase(main):010:0> scan 'rd_ns:leetable'
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405391883886, value=shangdi
100003 column=info:age, timestamp=1405390959464, value=301
100003 column=info:name, timestamp=1405390959464, value=show1
3 row(s) in 0.0250 seconds
现在,我们的目的是删除info列族中,时间戳为1405390959464的所有列数据:
Configuration conf = HBaseConfiguration.create();hbase(main):011:0> scan 'rd_ns:leetable'
HTable table = new HTable(conf, "rd_ns:leetable");
Delete delete = new Delete(Bytes.toBytes("100003"));
delete.deleteFamilyVersion(Bytes.toBytes("info"), 1405390959464L);
table.delete(delete);
table.close();
ROW COLUMN+CELL
100001 column=info:address, timestamp=1405304843114, value=longze
100001 column=info:age, timestamp=1405304843114, value=31
100001 column=info:name, timestamp=1405304843114, value=leon
100002 column=info:address, timestamp=1405305471343, value=caofang
100002 column=info:age, timestamp=1405305471343, value=30
100002 column=info:name, timestamp=1405305471343, value=show
100003 column=info:address, timestamp=1405391883886, value=shangdi
100003 column=info:age, timestamp=1405390728175, value=30
100003 column=info:name, timestamp=1405390728175, value=show
3 row(s) in 0.0250 seconds
可以看到,100003行的info列族,已经不存在时间戳为1405390959464的数据,比它更早版本的数据被查询出来,而info列族中时间戳不等于1405390959464的address列,不受该delete的影响。
八、完整代码
public class HbaseDemo01 {
private static Configuration configuration;
static {
//创建一个配置configuration
configuration = HBaseConfiguration.create();
configuration.set("hbase.zookeeper.quorum", "Master,Slave1,Slave2");
}
/**
* create建表
* @param tableName 表名
* @param columnFamilyName 列族名
*/
public static void createTable(String tableName,List<String> columnFamilyName){
try {
//创建一个管理admin
HBaseAdmin hBaseAdmin = new HBaseAdmin(configuration);
//创建表的特性
HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tableName));
if(hBaseAdmin.tableExists(tableName)){
//删表之前先禁用表
hBaseAdmin.disableTable(tableName);
hBaseAdmin.deleteTable(tableName);
System.out.println(tableName + " is exists");
}else{
//批量设置列族的特性
for(String cfName : columnFamilyName){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(cfName);
//给表添加列族
hTableDescriptor.addFamily(hColumnDescriptor);
}
hBaseAdmin.createTable(hTableDescriptor);
}
hBaseAdmin.close();
System.out.println("ok");
} catch (MasterNotRunningException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ZooKeeperConnectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* put插入数据
* @param tableName 表名
* @param rowKey 行键
* @param columnValues 插入数据值(两个map的key分别是列族和列)
* @return
*/
public static int putData(String tableName,String rowKey,Map<String,Map<String,String>> columnValues){
try {
//创建一个HTable,,参数为配置和表名
HTable hTable = new HTable(configuration, tableName);
//创建一个Put,一个put表示一行数据,参数为每行唯一的rowkey,再new一个put表示第二行数据
Put put = new Put(rowKey.getBytes());
//获取全部列族名
HColumnDescriptor[] columnFamilies = hTable.getTableDescriptor().getColumnFamilies();
//挨个提取出上边获得的全部列族名,匹配传入map参数对应的key,得到新map保存一个列族下所有的列和列值
for(HColumnDescriptor hColumnDescriptor : columnFamilies){
String cfName = hColumnDescriptor.getNameAsString();
Map<String,String> columnValueMap = columnValues.get(cfName);
//挨个遍历列名,添加列值到put
if(columnValueMap != null){
for(String columnName : columnValueMap.keySet()){
put.add(cfName.getBytes(), columnName.getBytes(), columnValueMap.get(columnName).getBytes());
}
}
}
hTable.put(put);
hTable.close();
return put.size();
//另外,用put列表批量插入数据效率较高,具体:
//List<Put> puts = new ArrayList<Put>();
//HTable table = new HTable(configuration, tableName);
//Put put = null;
//for(){
//put = new Put(rowKey.getBytes());
//put.add(family, qualifier, value);
//puts.add(put);
//}
//table.put(puts);
//table.close();
} catch (RetriesExhaustedWithDetailsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedIOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
/**
* 获取单行Get
* @param tableName 表名
* @param rowKey 行键
* @param cfName 列族名
* @param qualifierName 列名
*/
public static void getRow(String tableName,String rowKey,String cfName,String qualifierName){
try {
HTable hTable = new HTable(configuration,tableName);
//1.获取指定行的所有列族、所有列的最新版本数据
//创建一个Get,参数为rowkey
Get get = new Get(rowKey.getBytes());
//创建一个Result,由HTable实例的get方法得到,它的参数为Get实例
Result result = hTable.get(get);
for(Cell cell : result.rawCells()){
System.out.println("rowKey:" + new String(CellUtil.cloneRow(cell))
+ " cfName:" + new String(CellUtil.cloneFamily(cell))
+ " qualifierName:" + new String(CellUtil.cloneQualifier(cell))
+ " value:" + new String(CellUtil.cloneValue(cell)));
}
System.out.println("1ok");
//2.获取指定行中,指定列的最新版本数据
Get get2 = new Get(rowKey.getBytes());
get2.addColumn(cfName.getBytes(), qualifierName.getBytes());//在这里加入Get的各种方法,如时间戳和版本数等
Result rs2 = hTable.get(get2);
for(Cell cell : rs2.rawCells()){
System.out.println("rowKey:" + new String(CellUtil.cloneRow(cell))
+ " cfName:" + new String(CellUtil.cloneFamily(cell))
+ " qualifierName:" + new String(CellUtil.cloneQualifier(cell))
+ " value:" + new String(CellUtil.cloneValue(cell)));
}
hTable.close();
System.out.println("2ok");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 获取多行Scan
* @param tableName 表名
*/
public static void scanRows(String tableName){
try {
HTable hTable = new HTable(configuration, tableName);
//1.扫描指定行键范围,通过末尾加0,使得结果集包含StopRow
//创建一个Scan
Scan scan = new Scan();
scan.setStartRow("ZhangEr".getBytes());//按照rowkey排序,"ZhangEr"在"ZhangYi"前边,也可以不设置,就是扫描全部行
scan.setStopRow("ZhangYi0".getBytes());
//创建一个ResultScanner,由HTable的getScanner()方法得到,参数为Scan实例
ResultScanner resultScanner = hTable.getScanner(scan);
//和Get的区别是,多了一层遍历ResultScanner的循环
for(Result result : resultScanner){
for(Cell cell : result.rawCells()){
System.out.println("rowKey:" + new String(CellUtil.cloneRow(cell))
+ " cfName:" + new String(CellUtil.cloneFamily(cell))
+ " qualifierName:" + new String(CellUtil.cloneQualifier(cell))
+ " value:" + new String(CellUtil.cloneValue(cell))
+ " timeStamp:"+ cell.getTimestamp());
}
}
resultScanner.close();
System.out.println("1ok");
//2.结合过滤器,获取所有列族score的列math的值大于50小于60的行
//创建一个过滤器列表,参数是过滤器要求必须全部满足的意思
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
//创建两个过滤器,一个math的值大于等于50,一个小于60
SingleColumnValueFilter filter1 = new SingleColumnValueFilter("score".getBytes(), "math".getBytes(), CompareOp.GREATER_OR_EQUAL,"50".getBytes());
SingleColumnValueFilter filter2 = new SingleColumnValueFilter("score".getBytes(), "math".getBytes(), CompareOp.LESS, "60".getBytes());
//给过滤器列表添加上边的两个过滤器
filterList.addFilter(filter1);
filterList.addFilter(filter2);
//创建Scan,并设置过滤器
Scan scan2 = new Scan();
scan2.setFilter(filterList);
//创建ResultScanner开始两层循环
ResultScanner rs2 = hTable.getScanner(scan2);
for(Result r : rs2){
for(Cell cell : r.rawCells()){
System.out.println("rowKey:" + new String(CellUtil.cloneRow(cell))
+ " cfName:" + new String(CellUtil.cloneFamily(cell))
+ " qualifierName:" + new String(CellUtil.cloneQualifier(cell))
+ " value:" + new String(CellUtil.cloneValue(cell))
+ " timeStamp:"+ cell.getTimestamp());
}
}
rs2.close();
hTable.close();
System.out.println("2ok");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Delete删除表
*/
public static void deleteTable(){
try {
//创建HBaseAdmin
HBaseAdmin admin = new HBaseAdmin(configuration);
String tableName = "t_cdr";
//删除表前必须先disable表
if(admin.tableExists(tableName)){
admin.disableTable(tableName);
admin.deleteTable(tableName);
}
admin.close();
System.out.println("ok");
} catch (MasterNotRunningException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ZooKeeperConnectionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Delete删除数据
*/
public static void deleteData(){
try {
String tableName = "test02";
String rowKey01 = "01";
String rowKey02 = "02";
String cfName = "cf1";
String qualifierName = "name";
//创建一个HTable
HTable hTable = new HTable(configuration,tableName);
//1.删除整行的所有列族、所有列、所有版本
//创建一个Delete,参数为rowKey
Delete delete = new Delete(rowKey01.getBytes());
hTable.delete(delete);
System.out.println("1ok");
//2.删除指定列的最新版本
Delete d2 = new Delete(rowKey02.getBytes());
d2.deleteColumn(cfName.getBytes(), qualifierName.getBytes());//这里是写各种Delete方法的地方,比如控制删什么版本等
hTable.delete(d2);
hTable.close();
System.out.println("2ok");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 主函数
*/
public static void main(String[] args){
//1、Create建表
String tableName = "test01";
//List<String> columnFamilyName = new ArrayList<String>();
//columnFamilyName.add("info");
//columnFamilyName.add("address");
//columnFamilyName.add("score");
//createTable(tableName, columnFamilyName);
//2、Put插入或更新数据
//以下三行分别是rowkey、列族、列
String rowKey01 = "ZhangYi"; //我后来又插了个“ZhangEr”
//Map<String, Map<String, String>> columnFamilyMap01 = new HashMap<String, Map<String, String>>();
//Map<String, String> columnMap01 = new HashMap<String, String>();
//columnMap01.put("age", "23");
//columnMap01.put("phone","13854285991");
//columnFamilyMap01.put("info", columnMap01);
//Map<String, String> columnMap02 = new HashMap<String, String>();
//columnMap02.put("province", "shandong");
//columnMap02.put("city","qingdao");
//columnFamilyMap01.put("address", columnMap02);
//Map<String, String> columnMap03 = new HashMap<String, String>();
//columnMap03.put("english", "80");
//columnMap03.put("math", "90");
//columnFamilyMap01.put("score", columnMap03);
//int result01 = putData(tableName, rowKey01, columnFamilyMap01);
//System.out.println("put.size() as result01: " + result01);//应该是6(3列族x2列)
//3、 Get获取一行数据
//getRow(tableName, rowKey01, "info", "phone");
//4、Scan获取多行数据
//scanRows(tableName);//"ZhangEr"的math小于60
//5、Delete删除表
//deleteTable();//删除之前建的“t_cdr”表
//6、Delete删除数据
//deleteData();//建了个test02测试
}
}