实验3 熟悉常用的HBase操作

1. 实验目的

(1) 理解 HBase 在 Hadoop 体系结构中的角色;
(2) 熟练使用 HBase 操作常用的 Shell 命令;
(3) 熟悉 HBase 操作常用的 Java API。

2.实验平台

(1) 操作系统: Linux(Ubuntu-22.04.2-desktop-amd64);

(2) Hadoop 版本: 3.1.3;

(3) HBase版本:

(4) JDK 版本: 1.8;

(5) Java IDE: Eclipse。

3.实验步骤与结果

(一)编程实现以下指定功能,并用 Hadoop 提供的 HBase Shell 命令完成相同任务:
(1) 列出 HBase 所有的表的相关信息,例如表名;

运行结果+Java代码:

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
public class test1 {
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
/**
* @param args
* 建立连接
*/
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();
}
}
/*
* 查看已有表
* @throws IOException
*/
public static void listTables() throws IOException{
init();
@SuppressWarnings("deprecation")
HTableDescriptor hTableDescriptors [] = admin.listTables();
for(HTableDescriptor hTableDescriptor : hTableDescriptors){
System.out.println(hTableDescriptor.getNameAsString());
}
close();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
test1 t = new test1();
try{
System.out.println("以下为Hbase数据库中所存的表信息");
t.listTables();
}catch (IOException e){
e.printStackTrace();
}
}
}

HBase Shell 命令:

img

​ (2) 在终端打印出指定的表的所有记录数据;

运行结果+Java代码:

img

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import java.io.IOException;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.*;

import org.apache.hadoop.hbase.client.*;

import java.io.IOException;

import java.util.Scanner;

public class Test_2 {

public static Configuration configuration;

public static Connection connection;

public static Admin admin;

/**

* @param args

*/

//建立连接

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();

}

}

/**

* 根据表名查找表信息

*/

public static void getData(String tableName)throws IOException{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

ResultScanner scanner = table.getScanner(scan);

for(Result result:scanner)

{

showCell((result));

}

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("column Name(列名):"+new
String(CellUtil.cloneQualifier(cell))+" ");

System.out.println("value:(值)"+new
String(CellUtil.cloneValue(cell))+" ");

System.out.println();

}

}

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

Test_2 t =new Test_2();

System.out.println("请输入要查看的表名");

Scanner scan = new Scanner(System.in);

String tableName=scan.nextLine();

System.out.println("信息如下:");

t.getData(tableName);

}

}

HBase Shell 命令:

img

 (3) 向已经创建好的表添加和删除指定的列族或列;

运行结果+Java代码:

添加:

img

img

删除:

img

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
import java.io.IOException;

import java.util.Scanner;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.Cell;

import org.apache.hadoop.hbase.CellUtil;

import org.apache.hadoop.hbase.HBaseConfiguration;

import org.apache.hadoop.hbase.TableName;

import org.apache.hadoop.hbase.client.Admin;

import org.apache.hadoop.hbase.client.Connection;

import org.apache.hadoop.hbase.client.ConnectionFactory;

import org.apache.hadoop.hbase.client.Delete;

import org.apache.hadoop.hbase.client.Put;

import org.apache.hadoop.hbase.client.Result;

import org.apache.hadoop.hbase.client.ResultScanner;

import org.apache.hadoop.hbase.client.Scan;

import org.apache.hadoop.hbase.client.Table;

public class Test_3 {

public static Configuration configuration;

public static Connection connection;

public static Admin admin;

//建立连接

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();

}

}

/**

* 向某一行的某一列插入数据

* @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();

}

/**

* 根据表名查找表信息

*/

public static void getData(String tableName)throws IOException{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

ResultScanner scanner = table.getScanner(scan);

for(Result result:scanner)

{

showCell((result));

}

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("column Name(列名):"+new
String(CellUtil.cloneQualifier(cell))+" ");

System.out.println("value:(值)"+new
String(CellUtil.cloneValue(cell))+" ");

System.out.println();

}

}

/**

* 删除数据

* @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());

boolean flag2 =true;

while(flag2)

{

System.out.println("请输入你的选择 1-删除列族的所有数据2-指定列的数据");

Scanner scanner=new Scanner(System.in);

String chooseString = scanner.nextLine();

switch (chooseString) {

case "1":

{

//删除指定列族的所有数据

delete.addFamily(colFamily.getBytes());

table.delete(delete);

table.close();

close();

break;

}

case "2":

{

//删除指定列的数据

delete.addColumn(colFamily.getBytes(), col.getBytes());

table.delete(delete);

table.close();

close();

break;

}

default:

{

System.out.println(" 你的输入有误 !!! ");

table.close();

close();

break;

}

}

System.out.println(" 你要继续操作吗? 是-true 否-false ");

flag2=scanner.nextBoolean();

}

}

/**

* @param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

Test_3 t =new Test_3();

boolean flag =true;

while(flag)

{

System.out.println("------------向已经创建好的表中添加和删除指定的列簇或列--------------------");

System.out.println(" 请输入您要进行的操作 1- 添加 2-删除 ");

Scanner scan = new Scanner(System.in);

String choose1=scan.nextLine();

switch (choose1) {

case "1":

{

System.out.println("请输入要添加的表名");

String tableName=scan.nextLine();

System.out.println("请输入要添加的表的行键");

String rowKey=scan.nextLine();

System.out.println("请输入要添加的表的列簇");

String colFamily=scan.nextLine();

System.out.println("请输入要添加的表的列名");

String col=scan.nextLine();

System.out.println("请输入要添加的值");

String val=scan.nextLine();

try {

t.insertRow(tableName, rowKey, colFamily, col, val);

System.out.println("插入成功:");

t.getData(tableName);

} catch (IOException e) {

// TODO Auto-generated catch block

e.getMessage();

}

break;

}

case "2":

{

System.out.println("请输入要删除的表名");

String tableName=scan.nextLine();

System.out.println("请输入要删除的表的行键");

String rowKey=scan.nextLine();

System.out.println("请输入要删除的表的列簇");

String colFamily=scan.nextLine();

System.out.println("请输入要删除的表的列名");

String col=scan.nextLine();

try {

System.out.println("----------------------表的原本信息如下---------------------");

t.getData(tableName);

System.out.println("____________________________正在执行删除操作…\n");

t.deleteRow(tableName, rowKey, colFamily, col);

System.out.println("____________________________删除成功_______________\n");

System.out.println("---------------------删除后表的信息如下---------------------");

t.getData(tableName);

} catch (IOException e) {

// TODO Auto-generated catch block

e.getMessage();

}

break;

}

default:

{

System.out.println(" 你的操作有误 !!! ");

break;

}

}

System.out.println(" 你要继续操作吗? 是-true 否-false ");

flag=scan.nextBoolean();

}

System.out.println(" 程序已退出! ");

}

}

HBase Shell 命令:

添加:

img

删除:

img
(4) 清空指定的表的所有记录数据;

运行结果+Java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import java.io.IOException;

import java.util.Scanner;

import java.util.ArrayList;

import java.util.List;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.Cell;

import org.apache.hadoop.hbase.CellUtil;

import org.apache.hadoop.hbase.HBaseConfiguration;

import org.apache.hadoop.hbase.HColumnDescriptor;

import org.apache.hadoop.hbase.HTableDescriptor;

import org.apache.hadoop.hbase.TableName;

import org.apache.hadoop.hbase.client.Admin;

import org.apache.hadoop.hbase.client.Connection;

import org.apache.hadoop.hbase.client.ConnectionFactory;

import org.apache.hadoop.hbase.client.HBaseAdmin;

import org.apache.hadoop.hbase.client.Result;

import org.apache.hadoop.hbase.client.ResultScanner;

import org.apache.hadoop.hbase.client.Scan;

import org.apache.hadoop.hbase.client.Table;

import org.apache.hadoop.hbase.util.Bytes;

public class Test_4 {

public static Configuration configuration;

public static Connection connection;

public static Admin admin;

/**

* @param args

*/

//建立连接

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();

}

}

/**

* 清空制定的表的所有记录数据

* @param args

* @throws IOException

*/

public static void clearRows(String tableName) throws IOException{

init();

// HBaseAdmin admin1=new HBaseAdmin(configuration);

// HTableDescriptor tDescriptor=admin1.getTableDescriptor(Bytes.toBytes(tableName));
//读取了之前表的表名列簇等信息,然后再进行删除操作。总思想是先将原表结构保留下来,然后进行删除,再重新依据保存的信息重新创建表。

//备份表列族名

TableName tablename=TableName.valueOf(tableName);

HTableDescriptor tDescriptor = new

HTableDescriptor(TableName.valueOf(tableName));

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

ResultScanner scanner = table.getScanner(scan);

List<String> cloFamily = new ArrayList<String>();

for(Result result:scanner)

{

Cell[] cells = result.rawCells();

for(Cell cell:cells){

// System.out.println("column Family(列簇):"+newString(CellUtil.cloneFamily(cell))+" ");

cloFamily.add(new String(CellUtil.cloneFamily(cell)));

}

}

//删除表

admin.disableTable(tablename);

admin.deleteTable(tablename);

//重新建表

// HTableDescriptor tDescriptor = new

// HTableDescriptor(TableName.valueOf(tableName));

// tDescriptor.addFamily(new HColumnDescriptor("name"));

for(String cf : cloFamily)

{

tDescriptor.addFamily(new HColumnDescriptor(cf));

}

admin.createTable(tDescriptor);

close();

}

/**

* 根据表名查找表信息

*/

public static void getData(String tableName)throws IOException{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

ResultScanner scanner = table.getScanner(scan);

for(Result result:scanner)

{

showCell((result));

}

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("column Name(列名):"+new
String(CellUtil.cloneQualifier(cell))+" ");

System.out.println("value:(值)"+new
String(CellUtil.cloneValue(cell))+" ");

System.out.println();

}

}

public static void main(String[] args) {

// TODO Auto-generated method stub

Test_4 test_4=new Test_4();

Scanner scan = new Scanner(System.in);

System.out.println("请输入要清空的表名");

String tableName=scan.nextLine();

try {

System.out.println("表原来的信息:");

test_4.getData(tableName);

test_4.clearRows(tableName);

System.out.println("表已清空:");

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

HBase Shell 命令:

img (5) 统计表的行数。

运行结果+Java代码:

img

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import java.io.IOException;

import java.util.Scanner;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.HBaseConfiguration;

import org.apache.hadoop.hbase.TableName;

import org.apache.hadoop.hbase.client.Admin;

import org.apache.hadoop.hbase.client.Connection;

import org.apache.hadoop.hbase.client.ConnectionFactory;

import org.apache.hadoop.hbase.client.Result;

import org.apache.hadoop.hbase.client.ResultScanner;

import org.apache.hadoop.hbase.client.Scan;

import org.apache.hadoop.hbase.client.Table;

public class Test_5 {

public static Configuration configuration;

public static Connection connection;

public static Admin admin;

//建立连接

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();

}

}

public static void countRows (String tableName) throws IOException

{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

ResultScanner scanner =table.getScanner(scan);

int num = 0;

for(Result result = scanner.next();result!=null;result=scanner.next())

{

num++;

}

System.out.println("行数:"+num);

scanner.close();

close();

}

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

Test_5 test_5=new Test_5();

Scanner scan = new Scanner(System.in);

System.out.println("请输入要统计行数的表名");

String tableName=scan.nextLine();

test_5.countRows(tableName);

}

}

HBase Shell 命令:

img

(二) HBase 数据库操作

\1. 现有以下关系型数据库中的表和数据(见表14-3到表14-5),要求将其转换为适合于HBase 存储的表并插入数据:

表14-3学生表(Student)

学号(S_No) 姓名(S_Name) 性别(S_Sex) 年龄(S_Age)
2015001 Zhangsan male 23
2015002 Mary female 22
2015003 Lisi male 24

表14-4课程表(Course)

课程号(C_No) 课程名(C_Name) 学分(C_Credit)
123001 Math 2.0
123002 Computer Science 5.0
123003 English 3.0

表14-5选课表(SC)

学号(SC_Sno) 课程号(SC_Cno) 成绩(SC_Score)
2015001 123001 86
2015001 123003 69
2015002 123002 77
2015002 123003 99
2015003 123001 98
2015003 123002 95

学生表:

img

img

课程表

img

img

选课表:

img

img

img

\2. 请编程实现以下功能:

​ (1)createTable(String tableName, String[] fields)

​ 创建表,参数tableName为表的名称,字符串数组fields为存储记录各个字段名称的数组。要求当 HBase 已经存在名为 tableName 的表的时候,先删除原有的表,然后再创建新的表。

​ (2)addRecord(String tableName, String row, String[] fields, String[] values)
​ 向表tableName、行row(用S_Name表示)和字符串数组fields指定的单元格中添加对应的数据values。其中,fields中每个元素如果对应的列族下还有相应的列限定符的话,用“columnFamily:column”表示。例如,同时向“Math”、“Computer Science”、“English”三列添加成绩时,字符串数组fields为{“Score:Math”,”Score:Computer Science”, ”Score:English”},数组 values 存储这三门课的成绩。

​ (3)scanColumn(String tableName, String column)

​ 浏览表tableName某一列的数据,如果某一行记录中该列数据不存在,则返回null。要求当参数column为某一列族名称时,如果底下有若干个列限定符,则要列出每个列限定符代表的列的数据;当参数column为某一列具体名称(例如“Score:Math”)时,只需要列出该列的数据。
​ (4)modifyData(String tableName, String row, String column)

​ 修改表tableName,行row(可以用学生姓名S_Name表示),列column指定的单元格的数据。

​ (5)deleteRow(String tableName, String row)

​ 删除表tableName中row指定的行的记录。

JAVA代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.util.Scanner;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.hbase.Cell;

import org.apache.hadoop.hbase.CellUtil;

import org.apache.hadoop.hbase.HBaseConfiguration;

import org.apache.hadoop.hbase.HColumnDescriptor;

import org.apache.hadoop.hbase.HTableDescriptor;

import org.apache.hadoop.hbase.TableName;

import org.apache.hadoop.hbase.client.Admin;

import org.apache.hadoop.hbase.client.Connection;

import org.apache.hadoop.hbase.client.ConnectionFactory;

import org.apache.hadoop.hbase.client.Delete;

import org.apache.hadoop.hbase.client.Put;

import org.apache.hadoop.hbase.client.Result;

import org.apache.hadoop.hbase.client.ResultScanner;

import org.apache.hadoop.hbase.client.Scan;

import org.apache.hadoop.hbase.client.Table;

import org.apache.hadoop.hbase.util.Bytes;
public class Test_Two {
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
//建立连接
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();
}
}
/**
*jian表。参数tableName为表的名称,字符串数组fields为存储记录各个域名称的数组。
* 要求当HBase已经存在名为tableName的表时,先删除原有的表,然后再
* 创建新的表 field:列族
* @param myTableName 表名
* @param colFamily 列族名
* @throws IOException
*/
public static void createTable(String tableName,String[] fields)
throws IOException {
init();
TableName tablename = TableName.valueOf(tableName);
if(admin.tableExists(tablename)){
System.out.println("表已存在,将执行删除原表,重建新表!");
admin.disableTable(tablename);
admin.deleteTable(tablename);//删除原来的表
}
// HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
HTableDescriptor hTableDescriptor = new
HTableDescriptor(TableName.valueOf(tableName));
for(String str:fields){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);

hTableDescriptor.addFamily(hColumnDescriptor);

}

admin.createTable(hTableDescriptor);

System.out.println("表已创建成功");

close();

}

/**

* 向表 tableName、行 row(用 S_Name 表示)和字符串数组 fields
指定的单元格中

* 添加对应的数据 values。

* 其中,fields 中每个元素如果对应的列族下还有相应的列限定符的话,

* 用"columnFamily:column"表示。

* 例如,同时向"Math"、"Computer Science"、"English"三列添加成绩时,

* 字符串数组 fields 为{"Score:Math", "Score:Computer Science",
"Score:English"},

* 数组values 存储这三门课的成绩。

*/

public static void addRecord(String tableName,String rowKey,String
[]fields,String [] values) throws IOException {

init();

Table table = connection.getTable(TableName.valueOf(tableName));

for (int i = 0; i < fields.length; i++) {

Put put = new Put(rowKey.getBytes());

String [] cols = fields[i].split(":");

if(cols.length==1)

{

put.addColumn(cols[0].getBytes(), "".getBytes(),
values[i].getBytes());//因为当输入的是单列族,split仅读出一个字符字符串,即cols仅有一个元素

}

else {

put.addColumn(cols[0].getBytes(), cols[1].getBytes(),
values[i].getBytes());

}

table.put(put);

}

table.close();

close();

}

/**

* 根据表名查找表信息

*/

public static void getData(String tableName)throws IOException{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

ResultScanner scanner = table.getScanner(scan);

for(Result result:scanner)

{

showCell((result));

}

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("column Name(列名):"+new
String(CellUtil.cloneQualifier(cell))+" ");

System.out.println("value:(值)"+new
String(CellUtil.cloneValue(cell))+" ");

System.out.println();

}

}

/**

* 浏览表 tableName 某一列的数据,如果某一行记录中该列数据不存在,则返回
null。

* 要求当参数 column
为某一列族名称时,如果底下有若干个列限定符,则要列出每个列限定符代表的列的数据;

* 当参数 column
为某一列具体名称(例如"Score:Math")时,只需要列出该列的数据。

* @param tableName

* @param column

* @throws IOException

*/

public static void scanColumn (String tableName,String column) throws
IOException

{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Scan scan = new Scan();

String [] cols = column.split(":");

if(cols.length==1)

{

scan.addFamily(Bytes.toBytes(column));

}

else {

scan.addColumn(Bytes.toBytes(cols[0]),Bytes.toBytes(cols[1]));

}

ResultScanner scanner = table.getScanner(scan);

for (Result result = scanner.next(); result !=null;result =
scanner.next()) {

showCell(result);

}

table.close();

close();

}

/**

* 修改表 tableName,行 row(可以用学生姓名 S_Name 表示),列 column
指定的单元格的数据。

* @throws IOException

*/

public static void modifyData(String tableName,String rowKey,String
column,String value) throws IOException

{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Put put = new Put(rowKey.getBytes());

String [] cols = column.split(":");

if(cols.length==1)

{

put.addColumn(column.getBytes(),"".getBytes() ,
value.getBytes());//qualifier:列族下的列名

}

else {

put.addColumn(cols[0].getBytes(),cols[1].getBytes() ,
value.getBytes());//qualifier:列族下的列名

}

table.put(put);

table.close();

close();

}

/**

* 删除表 tableName 中 row 指定的行的记录。

* @throws IOException

*/

public static void deleteRow(String tableName,String rowKey) throws
IOException

{

init();

Table table = connection.getTable(TableName.valueOf(tableName));

Delete delete = new Delete(rowKey.getBytes());

table.delete(delete);

table.close();

close();

}

/**

* @param args

* @throws IOException

*/

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

Test_Two test_Two = new Test_Two();

boolean flag =true;

while(flag)

{

System.out.println("------------------------------------------------提供以下功能----------------------------------------------");

System.out.println(" 1- createTable(创建表 ,提供表名、列族名) ");

System.out.println(" 2- addRecord (向已知表名、行键、列簇的表添加值)");

System.out.println(" 3- ScanColumn(浏览表 某一列的数据) ");

System.out.println(" 4- modifyData(修改某表某行,某一列,指定的单元格的数据) ");

System.out.println(" 5- deleteRow(删除 某表 某行的记录) ");

System.out.println("------------------------------------------------------------------------------------------------------------------");

Scanner scan = new Scanner(System.in);

String choose1=scan.nextLine();

switch (choose1) {

case "1":

{

System.out.println("请输入要创建的表名");

String tableName=scan.nextLine();

System.out.println("请输入要创建的表的列族个数");

int Num=scan.nextInt();

String [] fields = new String[Num];

System.out.println("请输入要创建的表的列族");

/* Scanner scanner = new Scanner(System.in); scanner.next
如不是全局,即会记得上一次输出。相同地址读入值时*/

for(int i=0;i< fields.length;i++)

{

/*BufferedReader in = new BufferedReader(new
InputStreamReader(System.in));

fields[i] = in.readLine();*/

/*fields[i]=scan.next(); 因为之前没有输入过,所以可以读入新值*/

scan = new Scanner(System.in);

fields[i]=scan.nextLine();

}

System.out.println("正在执行创建表的操作");

test_Two.createTable(tableName,fields);

break;

}

case "2":

{

System.out.println("请输入要添加数据的表名");

String tableName=scan.nextLine();

System.out.println("请输入要添加数据的表的行键");

String rowKey=scan.nextLine();

System.out.println("请输入要添加数据的表的列的个数");

int num =scan.nextInt();

String fields[]=new String[num];

System.out.println("请输入要添加数据的表的列信息 共"+num+"条信息");

for(int i=0;i< fields.length;i++)

{

BufferedReader in3= new BufferedReader(new
InputStreamReader(System.in));

fields[i] = in3.readLine();

/*fields[i]=scan.next(); 因为之前没有输入过,所以可以读入新值*/

}

System.out.println("请输入要添加的数据信息 共"+num+"条信息");

String values[]=new String[num];

for(int i=0;i< values.length;i++)

{

BufferedReader in2 = new BufferedReader(new
InputStreamReader(System.in));

values[i] = in2.readLine();

}

System.out.println("原表信息");

test_Two.getData(tableName);

System.out.println("正在执行向表中添加数据的操作…\n");

test_Two.addRecord(tableName, rowKey, fields, values);

System.out.println("\n添加后的表的信息…");

test_Two.getData(tableName);

break;

}

case "3":

{

System.out.println("请输入要查看数据的表名");

String tableName=scan.nextLine();

System.out.println("请输入要查看数据的列名");

String column=scan.nextLine();

System.out.println("查看的信息如下:…\n");

test_Two.scanColumn(tableName, column);

break;

}

case "4":

{

System.out.println("请输入要修改数据的表名");

String tableName=scan.nextLine();

System.out.println("请输入要修改数据的表的行键");

String rowKey=scan.nextLine();

System.out.println("请输入要修改数据的列名");
String column=scan.nextLine();
System.out.println("请输入要修改的数据信息 ");
String value=scan.nextLine();
System.out.println("原表信息如下:…\n");
test_Two.getData(tableName);
System.out.println("正在执行向表中修改数据的操作…\n");
test_Two.modifyData(tableName, rowKey, column, value);
System.out.println("\n修改后的信息如下:…\n");
test_Two.getData(tableName);
break;
}
case "5":
{
System.out.println("请输入要删除指定行的表名");
String tableName=scan.nextLine();
System.out.println("请输入要删除指定行的行键");
String rowKey=scan.nextLine();
System.out.println("原表信息如下:…\n");
test_Two.getData(tableName);
System.out.println("正在执行向表中删除数据的操作…\n");
test_Two.deleteRow(tableName, rowKey);
System.out.println("\n删除后的信息如下:…\n");
test_Two.getData(tableName);
break;
}
default:
{
System.out.println(" 你的操作有误 !!! ");
break;
}
}
System.out.println(" 你要继续操作吗? 是-true 否-false ");
flag=scan.nextBoolean();
}
System.out.println(" 程序已退出! ");
}
}

(1) createTable(String tableName, String[] fields)

img

img

img

(2) addRecord(String tableName, String row, String[] fields, String[] values)

img

img

img

img

(3) scanColumn(String tableName, String column)

img

(4) modifyData(String tableName, String row, String column)

img

img

(5)deleteRow(String tableName, String row)

img

img

4.实验总结

1)实验完成情况

实验完成率:100%

2)出现的问题与解决方案

问题1: 对于HBase数据库操作不熟悉

解决:查阅http://dblab.xmu.edu.cn/blog/2442-2/ 发现HBase操作与SQL语言相比还是有较大的不同,但是命令都比较简单易懂,容易学习

img

问题2:在运行示例程序时一直出现如下图所示的错误,无法正确创建表和插入数据

img

解决: 重启hbase后得以正常运行

问题2:java清空数据表代码报错:

Table should have at least one column family. Set

hbase.table.sanity.checks to false at conf or table descriptor if you

want to bypass sanity checks

解决方法: 创建Hbase数据表时至少要有一个列族名,而清空数据表的java代码其实是删除了整个数据表再重新建一个有着原表列族名的空表,因此清空的前提是要清空的数据表中含有包括一个列的数据,此时只要先在原数据空中加入一个数据再执行清空数据库的代码即可。