一、 实验目的
本次实验通过使用终端和Java API对hbase进行增删改查操作,学习非关系型数据库的结构以及如何操作,理解非关系型数据库与关系数据库的对比,掌握如何使用菲关系型数据库hbase。
二、 实验内容
尽可能完成老师给出的内容,做了多少就写多少
三、 实验思路、结构
先在Linux命令行的方式下实现在hbase中建表,增删改查操作
然后再使用Elipse利用Java编程实现在hbase中建表,增删改查操作。
四、 实验结果
HBase中用create命令创建表,具体如下:
此时,即创建了一个“student”表,属性有:Sname,Ssex,Sage,Sdept,course。因为HBase的表中会有一个系统默认的属性作为行键,无需自行创建,默认为put命令操作中表名后第一个数据。创建完“student”表后,可通过describe命令查看“student”表的基本信息。命令执行截图如下:
然后执行HBase的增删改查操作。在添加数据时,HBase会自动为添加的数据添加一个时间戳,故在需要修改数据时,只需直接添加数据,HBase即会生成一个新的版本,从而完成“改”操作,旧的版本依旧保留,系统会定时回收垃圾数据,只留下最新的几个版本,保存的版本数可以在创建表的时候指定。
1.添加数据
HBase中用put命令添加数据,注意:一次只能为一个表的一行数据的一个列,也就是一个单元格添加一个数据,所以直接用shell命令插入数据效率很低,在实际应用中,一般都是利用编程操作数据。
此时为student表添加了学号为95001,名字为LiYing的一行数据,其行键为95001。因为HBase的表中会有一个系统默认的属性作为行键,无需自行创建,默认为put命令操作中表名后第一个数据。
此时即为95001行下的course列族的math列添加了一个数据。
2.删除数据
在HBase中用delete以及deleteall命令进行删除数据操作,它们的区别是:1. delete用于删除一个数据,是put的反向操作;2. deleteall操作用于删除一行数据。
此时删除了student表中95001行下的Ssex列的所有数据。
deleteall命令
Deleteall ‘student’, ‘95001’命令删除了95001行的所有列,即该行的全部数据。
3.查看数据
HBase中有两个用于查看数据的命令:1. get命令,用于查看表的某一行数据;2. scan命令用于查看某个表的全部数据。
get命令
返回的是‘student’表‘95001’行的数据。
scan命令
此时返回的是’student’表的全部数据。
还可以查询标的历史数据
查询表的历史版本,需要两步。
(1).在创建表的时候,指定保存的版本数(假设指定为5)
(2).插入数据然后更新数据,使其产生历史版本数据,注意:这里插入数据和更新数据都是用put命令
(3).查询时,指定查询的历史版本数。默认会查询出最新的数据。(有效取值为1到5)
4.删除表
删除表有两步,第一步先让该表不可用,第二步删除表。
使用Elipse编程实现对hbase的增删改查
代码为:
1 import org.apache.hadoop.conf.Configuration; 2 import org.apache.hadoop.hbase.*; 3 import org.apache.hadoop.hbase.client.*; 4 import java.io.IOException; 5 6 public class ExampleForHbase 7 { 8 public static Configuration configuration; 9 public static Connection connection; 10 public static Admin admin; 11 12 //主函数中的语句请逐句执行,只需删除其前的//即可,如:执行insertRow时请将其他语句注释 13 public static void main(String[] args)throws IOException 14 { 15 //创建一个表,表名为Score,列族为sname,course 16 //createTable("Score",new String[]{"sname","course"}); 17 18 //在Score表中插入一条数据,其行键为95001,sname为Mary(因为sname列族下没有子列所以第四个参数为空) 19 //等价命令:put 'Score','95001','sname','Mary' 20 //insertRow("Score", "95001", "sname", "", "Mary"); 21 //在Score表中插入一条数据,其行键为95001,course:Math为88(course为列族,Math为course下的子列) 22 //等价命令:put 'Score','95001','score:Math','88' 23 //insertRow("Score", "95001", "course", "Math", "88"); 24 //在Score表中插入一条数据,其行键为95001,course:English为85(course为列族,English为course下的子列) 25 //等价命令:put 'Score','95001','score:English','85' 26 //insertRow("Score", "95001", "course", "English", "85"); 27 28 //1、删除Score表中指定列数据,其行键为95001,列族为course,列为Math 29 //执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码取消注释注释,将删除制定列族的代码注释 30 //等价命令:delete 'Score','95001','score:Math' 31 //deleteRow("Score", "95001", "course", "Math"); 32 33 //2、删除Score表中指定列族数据,其行键为95001,列族为course(95001的Math和English的值都会被删除) 34 //执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码注释,将删除制定列族的代码取消注释 35 //等价命令:delete 'Score','95001','score' 36 //deleteRow("Score", "95001", "course", ""); 37 38 //3、删除Score表中指定行数据,其行键为95001 39 //执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码注释,以及将删除制定列族的代码注释 40 //等价命令:deleteall 'Score','95001' 41 //deleteRow("Score", "95001", "", ""); 42 43 //查询Score表中,行键为95001,列族为course,列为Math的值 44 //getData("Score", "95001", "course", "Math"); 45 //查询Score表中,行键为95001,列族为sname的值(因为sname列族下没有子列所以第四个参数为空) 46 //getData("Score", "95001", "sname", ""); 47 48 //删除Score表 49 //deleteTable("Score"); 50 } 51 52 //建立连接 53 public static void init() 54 { 55 configuration = HBaseConfiguration.create(); 56 configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase"); 57 try 58 { 59 connection = ConnectionFactory.createConnection(configuration); 60 admin = connection.getAdmin(); 61 } 62 catch (IOException e) 63 { 64 e.printStackTrace(); 65 } 66 } 67 //关闭连接 68 public static void close() 69 { 70 try 71 { 72 if(admin != null) 73 { 74 admin.close(); 75 } 76 if(null != connection) 77 { 78 connection.close(); 79 } 80 } 81 catch (IOException e) 82 { 83 e.printStackTrace(); 84 } 85 } 86 87 /** 88 * 建表。HBase的表中会有一个系统默认的属性作为主键,主键无需自行创建,默认为put命令操作中表名后第一个数据,因此此处无需创建id列 89 * @param myTableName 表名 90 * @param colFamily 列族名 91 * @throws IOException 92 */ 93 public static void createTable(String myTableName,String[] colFamily) throws IOException 94 { 95 96 init(); 97 TableName tableName = TableName.valueOf(myTableName); 98 99 if(admin.tableExists(tableName)) 100 { 101 System.out.println("talbe is exists!"); 102 } 103 else 104 { 105 HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName); 106 for(String str:colFamily) 107 { 108 HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str); 109 hTableDescriptor.addFamily(hColumnDescriptor); 110 } 111 admin.createTable(hTableDescriptor); 112 System.out.println("create table success"); 113 } 114 close(); 115 } 116 /** 117 * 删除指定表 118 * @param tableName 表名 119 * @throws IOException 120 */ 121 public static void deleteTable(String tableName) throws IOException 122 { 123 init(); 124 TableName tn = TableName.valueOf(tableName); 125 if (admin.tableExists(tn)) 126 { 127 admin.disableTable(tn); 128 admin.deleteTable(tn); 129 } 130 close(); 131 } 132 133 /** 134 * 查看已有表 135 * @throws IOException 136 */ 137 public static void listTables() throws IOException 138 { 139 init(); 140 HTableDescriptor hTableDescriptors[] = admin.listTables(); 141 for(HTableDescriptor hTableDescriptor :hTableDescriptors) 142 { 143 System.out.println(hTableDescriptor.getNameAsString()); 144 } 145 close(); 146 } 147 /** 148 * 向某一行的某一列插入数据 149 * @param tableName 表名 150 * @param rowKey 行键 151 * @param colFamily 列族名 152 * @param col 列名(如果其列族下没有子列,此参数可为空) 153 * @param val 值 154 * @throws IOException 155 */ 156 public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException 157 { 158 init(); 159 Table table = connection.getTable(TableName.valueOf(tableName)); 160 Put put = new Put(rowKey.getBytes()); 161 put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes()); 162 table.put(put); 163 table.close(); 164 close(); 165 } 166 167 /** 168 * 删除数据 169 * @param tableName 表名 170 * @param rowKey 行键 171 * @param colFamily 列族名 172 * @param col 列名 173 * @throws IOException 174 */ 175 public static void deleteRow(String tableName,String rowKey,String colFamily,String col) throws IOException 176 { 177 init(); 178 Table table = connection.getTable(TableName.valueOf(tableName)); 179 Delete delete = new Delete(rowKey.getBytes()); 180 //删除指定列族的所有数据 181 //delete.addFamily(colFamily.getBytes()); 182 //删除指定列的数据 183 //delete.addColumn(colFamily.getBytes(), col.getBytes()); 184 185 table.delete(delete); 186 table.close(); 187 close(); 188 } 189 /** 190 * 根据行键rowkey查找数据 191 * @param tableName 表名 192 * @param rowKey 行键 193 * @param colFamily 列族名 194 * @param col 列名 195 * @throws IOException 196 */ 197 public static void getData(String tableName,String rowKey,String colFamily,String col)throws IOException 198 { 199 init(); 200 Table table = connection.getTable(TableName.valueOf(tableName)); 201 Get get = new Get(rowKey.getBytes()); 202 get.addColumn(colFamily.getBytes(),col.getBytes()); 203 Result result = table.get(get); 204 showCell(result); 205 table.close(); 206 close(); 207 } 208 /** 209 * 格式化输出 210 * @param result 211 */ 212 public static void showCell(Result result) 213 { 214 Cell[] cells = result.rawCells(); 215 for(Cell cell:cells) 216 { 217 System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" "); 218 System.out.println("Timetamp:"+cell.getTimestamp()+" "); 219 System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" "); 220 System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" "); 221 System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" "); 222 } 223 } 224 }
建表成功
在执行完代码中的所有插入操作以后可以看到表中数据为:
执行三个不同层次的删除操作后表中已经没有数据了
再重新执行一个插入数据的操作
然后执行第一个getData操作
再执行第二个getData操作
最后删除表。
五、 心得体会
做实验的时候要细心,注意具体导入的是哪个地方的jar包