本周也不知道是第几周,总结就完事了。这周学习的东西有很多,除了熟悉上周学习的Hadoop之外,软考也在进行备战中。本周收获最大的是Hbase方面的学习。
Hbase是基于Hadoop的,分布式、面向列的的开源数据库。是大数据学习中一大基础。Hbase的相关配置比Hadoop简单,由于本人的电脑运行内存只有8G,不能支持虚拟机多开,因此安装的Hbase与Hadoop一样是伪分布式的,下面附上个人认为比较详细的安装教程贴,对应Hbase版本是1.3.1
伪分布式Hbase配置: https://blog.csdn.net/qq_42250913/article/details/86184606
Hbase的shell命令在网上有详细说明,在这里不多赘述。主要说明一下maven导入Hbase以及java的API操作。
pom.xml
1 <dependency> 2 <groupId>org.apache.hbase</groupId> 3 <artifactId>hbase-client</artifactId> 4 <version>1.3.1</version> 5 </dependency> 6 <dependency> 7 <groupId>org.apache.hbase</groupId> 8 <artifactId>hbase-server</artifactId> 9 <version>1.3.1</version> 10 </dependency>
注意!!!导入Hbase的前提要求是Hadoop导入。
通过Hbase的java API操作完成对数据的增删改查,实现方式有很多,下面附上个人查找资料找到的一些实现方式。
1 import java.io.IOException; 2 import org.apache.hadoop.conf.Configuration; 3 import org.apache.hadoop.hbase.*; 4 import org.apache.hadoop.hbase.client.*; 5 import org.apache.hadoop.hbase.util.Bytes; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 public class hbase_try { 10 //以下是必要参数,因此static提前运行,用于连接Hbase 11 private static Connection connection; 12 private static Admin admin; 13 static { 14 try { 15 Configuration conf=HBaseConfiguration.create(); 16 conf.set("hbase.zookeeper.quorum","hadoop01"); 17 connection = ConnectionFactory.createConnection(conf); 18 admin = connection.getAdmin(); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 } 23 public static void main(String[]args) throws IOException { 24 String[] family={"k1","k2"}; 25 String table="trytable"; 26 Bean bean=new Bean("001","PYD","20"); 27 Bean bean1=new Bean("002","KKK","21"); 28 Bean bean2=new Bean("003","PPP","22"); 29 CreateTable(table,family); 30 insertData(table,bean); 31 insertData(table,bean1); 32 insertData(table,bean2); 33 //获取未加处理的原生数据 34 getNoDealData(table); 35 //获取该列数据 36 Bean rbean=getDataRowkey(table,"bean-001"); 37 System.out.println(rbean.toString()); 38 //获取指定单项数据 39 String bean_user=getCellData(table,"bean-001","k1","user"); 40 System.out.println(bean_user); 41 //获取表中全部数据 42 List<Bean> list=getAllData(table); 43 for(Bean beanc:list){ 44 System.out.println(beanc.toString()); 45 } 46 //删除表中指定cell数据 47 deleteByRowkey(table,"bean-003"); 48 List<Bean> list1=getAllData(table); 49 for(Bean beanc1:list1){ 50 System.out.println(beanc1.toString()); 51 } 52 //删除表 53 DeleteTable(table); 54 } 55 //创建表 56 public static void CreateTable(String tablename,String[]family)throws IOException{ 57 TableName tname=TableName.valueOf(tablename); 58 if(admin.tableExists(tname)){ 59 System.out.println("table Exists!"); 60 }else{ 61 HTableDescriptor hTableDescriptor=new HTableDescriptor(TableName.valueOf(tablename)); 62 for(String f:family){ 63 HColumnDescriptor hColumnDescriptor=new HColumnDescriptor(f); 64 hTableDescriptor.addFamily(hColumnDescriptor); 65 } 66 admin.createTable(hTableDescriptor); 67 System.out.println("Over!"); 68 } 69 } 70 //删除表 71 public static void DeleteTable(String tablename){ 72 try{ 73 TableName tname=TableName.valueOf(tablename); 74 admin.disableTable(tname); 75 admin.deleteTable(tname); 76 System.out.println("Over!"); 77 }catch (Exception e){ 78 e.printStackTrace(); 79 } 80 } 81 //插入数据 82 public static void insertData(String tablename,Bean bean)throws IOException{ 83 TableName tname=TableName.valueOf(tablename); 84 Put put=new Put(("bean-"+bean.getId()).getBytes()); 85 put.addColumn("k1".getBytes(),"user".getBytes(),bean.getUser().getBytes()); 86 put.addColumn("k2".getBytes(),"num".getBytes(),bean.getNum().getBytes()); 87 Table table= connection.getTable(tname); 88 table.put(put); 89 System.out.println("Over!"); 90 } 91 //获取原始数据 92 public static void getNoDealData(String tablename){ 93 try{ 94 Table table=connection.getTable(TableName.valueOf(tablename)); 95 Scan scan=new Scan(); 96 ResultScanner resultScanner=table.getScanner(scan); 97 for(Result result:resultScanner){ 98 System.out.println("scan:"+result); 99 } 100 }catch (Exception e){ 101 e.printStackTrace(); 102 } 103 } 104 //根据Rowkey查询 105 public static Bean getDataRowkey(String tablename,String rowkey)throws IOException{ 106 Table table=connection.getTable(TableName.valueOf(tablename)); 107 Get get=new Get(rowkey.getBytes()); 108 Bean bean=new Bean(); 109 bean.setId(rowkey); 110 //判断是否有数据 111 if(!get.isCheckExistenceOnly()){ 112 Result result=table.get(get); 113 for(Cell cell:result.rawCells()){ 114 String colName=Bytes.toString(cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength()); 115 String value=Bytes.toString(cell.getValueArray(),cell.getValueOffset(),cell.getValueLength()); 116 if(colName.equals("user")){ 117 bean.setUser(value); 118 } 119 if(colName.equals("num")){ 120 bean.setNum(value); 121 } 122 } 123 } 124 return bean; 125 } 126 //查询指定单cell的内容 127 public static String getCellData(String tablename,String rowkey,String family,String col){ 128 try{ 129 Table table=connection.getTable(TableName.valueOf(tablename)); 130 String result=null; 131 Get get=new Get(rowkey.getBytes()); 132 if(!get.isCheckExistenceOnly()){ 133 get.addColumn(Bytes.toBytes(family),Bytes.toBytes(col)); 134 Result res=table.get(get); 135 byte[]resByte=res.getValue(Bytes.toBytes(family),Bytes.toBytes(col)); 136 return result=Bytes.toString(resByte); 137 }else{ 138 return result="NO Data!"; 139 } 140 }catch (Exception e){ 141 e.printStackTrace(); 142 } 143 return "ERROR!"; 144 } 145 //查询指定表名中所有数据 146 public static List<Bean> getAllData(String tablename){ 147 Table table=null; 148 List<Bean> list=new ArrayList<Bean>(); 149 try{ 150 table=connection.getTable(TableName.valueOf(tablename)); 151 ResultScanner results=table.getScanner(new Scan()); 152 Bean bean=null; 153 for(Result result:results){ 154 String id=new String(result.getRow()); 155 System.out.println("Bean:"+new String(result.getRow())); 156 bean=new Bean(); 157 for(Cell cell:result.rawCells()){ 158 String row=Bytes.toString(cell.getRowArray(),cell.getRowOffset(),cell.getRowLength()); 159 String family=Bytes.toString(cell.getFamilyArray(),cell.getFamilyOffset(),cell.getFamilyLength()); 160 String colName=Bytes.toString(cell.getQualifierArray(),cell.getQualifierOffset(),cell.getQualifierLength()); 161 String value=Bytes.toString(cell.getValueArray(),cell.getValueOffset(),cell.getValueLength()); 162 bean.setId(row); 163 if(colName.equals("user")){ 164 bean.setUser(value); 165 } 166 if(colName.equals("num")) { 167 bean.setNum(value); 168 } 169 } 170 list.add(bean); 171 } 172 }catch (Exception e){ 173 e.printStackTrace(); 174 } 175 return list; 176 } 177 //删除指定cell数据 178 public static void deleteByRowkey(String tablename,String rowkey)throws IOException{ 179 Table table=connection.getTable(TableName.valueOf(tablename)); 180 Delete delete=new Delete(Bytes.toBytes(rowkey)); 181 table.delete(delete); 182 System.out.println("Over!"); 183 } 184 }
注意Hbase的一些方法是旧方法,若使用IDEA编写的话会发现一些方法被划上了线,因此记得查找新的方法如何实现,虽然老方法也不影响使用。比如上述代码中创建表的那一块,原构造方法没有使用Table.valueOf()这一方式。
在实际应用中我们查找不可能像刚才的代码那样简单查找,而且Hbase是按行列来查询的,若想像SQL语句那样按条件查找的话,需要使用过滤器Filter。Filter有很多种类,本周应测试要求,系统学习了SingleColumnValueFilter。先附上代码。
1 public static String getData(String JGMC,String SZDY,String JSXQMC,String GJZ) throws IOException, JSONException { 2 Table table=connection.getTable(TableName.valueOf("OrganForm2")); 3 Scan scan=new Scan(); 4 JSONArray array=new JSONArray(); 5 if(JGMC.trim().length()>0) { 6 FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE); 7 SingleColumnValueFilter filter = new SingleColumnValueFilter(Bytes.toBytes("O1"), 8 Bytes.toBytes("JGMC"), CompareFilter.CompareOp.EQUAL ,Bytes.toBytes(JGMC)); 9 filterList.addFilter(filter); 10 scan.setFilter(filterList); 11 } 12 13 if(SZDY.trim().length()>0) { 14 FilterList filterList1 = new FilterList(FilterList.Operator.MUST_PASS_ONE); 15 SingleColumnValueFilter filter1 = new SingleColumnValueFilter(Bytes.toBytes("O1"), 16 Bytes.toBytes("SZDY"), CompareFilter.CompareOp.EQUAL ,Bytes.toBytes(SZDY)); 17 filterList1.addFilter(filter1); 18 scan.setFilter(filterList1); 19 } 20 21 if(JSXQMC.trim().length()>0) { 22 FilterList filterList2 = new FilterList(FilterList.Operator.MUST_PASS_ONE); 23 SingleColumnValueFilter filter2 = new SingleColumnValueFilter(Bytes.toBytes("O1"), 24 Bytes.toBytes("jsxqmc"), CompareFilter.CompareOp.EQUAL ,Bytes.toBytes(JSXQMC)); 25 filterList2.addFilter(filter2); 26 scan.setFilter(filterList2); 27 } 28 29 if(GJZ.trim().length()>0) { 30 FilterList filterList3 = new FilterList(FilterList.Operator.MUST_PASS_ONE); 31 SingleColumnValueFilter filter3 = new SingleColumnValueFilter(Bytes.toBytes("O1"), 32 Bytes.toBytes("gjz"), CompareFilter.CompareOp.EQUAL ,Bytes.toBytes(GJZ)); 33 filterList3.addFilter(filter3); 34 scan.setFilter(filterList3); 35 } 36 37 ResultScanner resultScanner=table.getScanner(scan); 38 for(Result result:resultScanner){ 39 System.out.println(Bytes.toString(result.getRow())); 40 JSONObject object=new JSONObject(); 41 object.put("JGMC", Bytes.toString(result.getValue(Bytes.toBytes("O1"), Bytes.toBytes("JGMC")))); 42 object.put("SZDY", Bytes.toString(result.getValue(Bytes.toBytes("O1"), Bytes.toBytes("SZDY")))); 43 object.put("JSXQMC", Bytes.toString(result.getValue(Bytes.toBytes("O1"), Bytes.toBytes("JSXQMC")))); 44 object.put("GJZ", Bytes.toString(result.getValue(Bytes.toBytes("O1"), Bytes.toBytes("GJZ")))); 45 object.put("YJLX", Bytes.toString(result.getValue(Bytes.toBytes("O1"), Bytes.toBytes("YJLX")))); 46 object.put("JGSX", Bytes.toString(result.getValue(Bytes.toBytes("O1"), Bytes.toBytes("JGSX")))); 47 array.add(object); 48 } 49 return array.toString(); 50 }
这里因为需要与HTML进行ajax交互,所以使用了json数组封装。由于我们遍历的数据不止一条,可能符合条件的语句有多条。所以需要将结果组合在一起。因此使用到了FilterList,它会在scan遍历后,将所有符合条件的数据条合在一起返回,注意此时直接输出的结果并不是存入时的数据,而是为了能够存入库而经过一次处理的"原生"数据,为了拿到真正的数据我们需要对每一条Filter进行处理,也就是代码中的Bytes.toString方法。SingleColunmnValueFilter在使用中对应的三个Bytes参数分别为"列族","列值",以及查询用的条件值。
最后,说明一下在测试过程中踩到的坑。注意我们在提取数据的时候使用的是Bytes.toString方法进行byte[]转化成String,当我们在存入数据时同样要使用Bytes.toBytes进行String转化byte[]操作,有些帖子所写的转换操作是str.getBytes(),然而这样操作,英文数字以及一些字符可以正常读取,但是中文就会出现乱码问题!因此强烈建议使用Bytes.toBytes(str)进行转换存储。
Put put=new Put(("id-"+bean.getWJID()).getBytes()); //推荐写法(二者存入的表结构不同,仅针对Bytes.toBytes(str)和str.getBytes()说明) put.addColumn(Bytes.toBytes("O1"),Bytes.toBytes("SFSH"),Bytes.toBytes(bean.getSFSH())); //不推荐写法:put.addColumn("k1".getBytes(),"user".getBytes(),bean.getUser().getBytes());