大数据学习之路48-hbase的客户端api-DML操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37050372/article/details/82025195

1.插入数据

这次我们不需要去拿admin,因为我们不是管理表,而是直接对表进行操作

我们在拿到表之后如果想插入数据的话,要么插入一个put对象,要么插入一个put的list

而put是对我们需要放进的数据的封装

插入一行数据:

  /**
	   * 插入一行数据
	 * @throws IOException 
	   */
	  @Test
	  public void testPut() throws IOException{
		      Table table = conn.getTable(TableName.valueOf("t_1"));
		      //put中的参数为行键
		      Put put = new Put("rk001".getBytes());	
		      //参数依次为列族,key,value
		      //hbase提供了将各种数据转换为byte的方法Bytes.toBytes()
		      put.addColumn("f1".getBytes(), "uid".getBytes(), Bytes.toBytes(1));
		      put.addColumn("f1".getBytes(), "uname".getBytes(), Bytes.toBytes("zhangsan"));
		      put.addColumn("f1".getBytes(), "uage".getBytes(), Bytes.toBytes(18));
		      table.put(put);
		      table.close();
		      conn.close();
		      
	  }

成功截图:

插入多行:

 /**
	   * 插入多行数据
	 * @throws IOException 
	   */
	  @Test
		  public void testPuts() throws IOException{
			  Table table = conn.getTable(TableName.valueOf("t_1"));
			  Put put = new Put("rk001".getBytes());
			  put.addColumn("f1".getBytes(), "sex".getBytes(), Bytes.toBytes("male"));
			  put.addColumn("f1".getBytes(),"address".getBytes(),Bytes.toBytes("taiyuan") );
			  
			  Put put2 = new Put("rk002".getBytes());
			  put2.addColumn("f2".getBytes(),"uid".getBytes() , Bytes.toBytes(2));
			  put2.addColumn("f2".getBytes(), "uname".getBytes(),Bytes.toBytes("zhangs4"));
			  ArrayList<Put> list = new ArrayList<Put>();
			  list.add(put);
			  list.add(put2);
			  table.put(list);
			  table.close();
			  conn.close();
		  }

成功截图:

上面生成的乱码其实是对整数进行编码之后的结果。

更新数据:

更新数据的本质就是重新构造一个相同key,但value不同的put对象,插入数据库

 /**
	      * 更新数据
	     * @throws IOException 
	      */
	  @Test
	     public void testUpdate() throws IOException{
	    	    Table table = conn.getTable(TableName.valueOf("t_1"));
	    	    Put put = new Put("rk002".getBytes());
	    	    put.addColumn("f2".getBytes(), "uname".getBytes(), Bytes.toBytes("zhang5"));
	    	    table.put(put);
	    	    table.close();
	    	    conn.close();
	     }

成功截图:

删除数据:

删除一行中的某个值:

  @Test
		  public void testDelete() throws IOException{
			    Table table = conn.getTable(TableName.valueOf("t_1"));
			    Delete delete = new Delete("rk001".getBytes());
			    delete.addColumn("f1".getBytes(), "uname".getBytes());
			    
			    Delete delete2 = new Delete("rk002".getBytes());
			    delete2.addColumn("f2".getBytes(), "uname".getBytes());
			    ArrayList<Delete> list = new ArrayList<Delete>();
			    list.add(delete);
			    list.add(delete2);
			    table.delete(list);
		  }

成功截图:

我们可以看见删除之后数据不见了,而且还有一个地方值得注意,就是我们之前更新过的值,被删除之后回退到原来的版本 。

删除整行:

删除整行只需要指定行键即可

 @Test
	     public void testDelete2() throws IOException{
	    	 Table table = conn.getTable(TableName.valueOf("t_1"));
	    	 Delete delete = new Delete("rk001".getBytes());
	    	 table.delete(delete);
	     }

成功截图:

对一行进行查询:

我们如果使用下面这种方式的话会有问题:

会出现乱码如下:

原因是什么?

原因就是无论我们使用getFamilyArray(),还是getQualifierArray(),他都会将那一个单元格的数据二进制数据都给我们,并不是说我们要哪个就给我们返回哪个字段。而且里面还带的一些二进制数据自带的分隔符。所以我们可以指定某个字段的起始偏移量和终止偏移量。那么他们为什么要这样做呢?就是因为开发者没有封装好,本身就是非常底层的东西。

我们可以像下面这样操作。

运行结果如下:

看到箭头指向的那个值仍为乱码,这是因为当初传值的时候传进去的是int值,而我们的value值的类型如果是多样的,这样就会造成麻烦,还需要进一步的判断。所以为了避免这种麻烦,我们最好当初传值的时候都传String,这样我们可以将String转换为我们需要的类型。就会方便很多。

以下贴出代码:

package com.test.hbase;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Before;
import org.junit.Test;

public class HbaseClientQuery {
	Connection conn = null;
	
	 @Before
     public void init() throws IOException{
		 Configuration  conf = HBaseConfiguration.create();
		     conf.set("hbase.zookeeper.quorum","marshal:2181,marshal01:2181,marshal02:2181,marshal03:2181,marshal04:2181,marshal05:2181" );
    	    conn = ConnectionFactory.createConnection(conf);
     }
	 
	 /**
	  * 对一行进行查询
	 * @throws IOException 
	  */
	 @Test
	 public void  testGet() throws IOException{
		 Table table = conn.getTable(TableName.valueOf("t_1"));
		 Get get = new Get("rk002".getBytes());
		 
		 Result result = table.get(get);
		 /**
		  * 从返回结果中去除指定key的value
		  */
		 //这里返回的是一个字节数组中,因为他也不知道你存储的是什么类型
		 byte[] value = result.getValue("f2".getBytes(), "uid".getBytes());
	     //我们有工具实现转型
		 int uid = Bytes.toInt(value);
		 System.out.println(uid);
		 //取出返回结果中所有key和value
		 //一对key,value相当于一个cell,这个scanner相当于一个迭代器
		 CellScanner cellScanner = result.cellScanner();
		 while(cellScanner.advance()){
			 Cell current = cellScanner.current();
			 byte[] rowArray = current.getRowArray();
			 String rowkey = Bytes.toString(rowArray,current.getRowOffset(),current.getRowLength());
			 byte[] familyArray = current.getFamilyArray();
			 String f = Bytes.toString(familyArray,current.getFamilyOffset(),current.getFamilyLength());
			   byte[] qualifierArray = current.getQualifierArray();
			 String q = Bytes.toString(qualifierArray,current.getQualifierOffset(),current.getQualifierLength());
			 byte[] valueArray = current.getValueArray();   
			 String v = Bytes.toString(valueArray,current.getValueOffset(),current.getValueLength());
			 
			 System.out.println(rowkey+","+f+":"+q+","+v);
			  
			 }
		 table.close();
		 conn.close();
	 
	 }
}

这样只能拿到一行的数据,如果我们想拿到多行的话,我们可以多new几个Get然后放入list中。

然后使用table.get(list);获取,这样就能拿到多行。

但是这样实际上还是一行一行去取的,我们还有一种便捷的方式:就是scan取多行

Scan可以指定起始行,还有结束行。如果不指定就是全表查询。但是最好不要这样做。因为hbase的表特别大。动不动就是几万亿行。

而且Scan还带过滤器,可以加一下条件过滤,不然数据真的太多了。

先看看我们表中的数据:

以下贴出代码:

public void printResult(Result result) throws IOException {
		CellScanner cellScanner = result.cellScanner();
		 while(cellScanner.advance()){
			 Cell current = cellScanner.current();
			 byte[] rowArray = current.getRowArray();
			 String rowkey = Bytes.toString(rowArray,current.getRowOffset(),current.getRowLength());
			 byte[] familyArray = current.getFamilyArray();
			 String f = Bytes.toString(familyArray,current.getFamilyOffset(),current.getFamilyLength());
			   byte[] qualifierArray = current.getQualifierArray();
			 String q = Bytes.toString(qualifierArray,current.getQualifierOffset(),current.getQualifierLength());
			 byte[] valueArray = current.getValueArray();   
			 String v = Bytes.toString(valueArray,current.getValueOffset(),current.getValueLength());
			 
			 System.out.println(rowkey+","+f+":"+q+","+v);
			  
			 }
	}
	 @Test
	 public void testScan() throws IOException{
		 Table table = conn.getTable(TableName.valueOf("t_1"));
		 //扫描范围    含首不含尾
		   Scan scan = new Scan("rk001".getBytes(),"rk004".getBytes());
		    ResultScanner scanner = table.getScanner(scan);
		    Iterator<Result> iterator = scanner.iterator();
		    while(iterator.hasNext()){
		    	Result next = iterator.next();
		    	printResult(next);
		    }
		    table.close();
		    conn.close();
	 }

成功截图:

那么假如说有这样的场景:

我们的数据是这样的:

我们希望取到rk005,可是

因为使用扫描方法的话含首不含尾,我们又不知道rk005的下一个有几个0我们就可以使用八进制的0或者16进制的0

代码如下:

Scan scan = new Scan("rk001".getBytes(),("rk005"+"\000").getBytes());

Scan加过滤器:

我们如果加过滤器的话,scan方法就只有两个参数啦,一个是起始行,另一个是过滤器。

过滤器分为:行过滤器,列族过滤器,列过滤器,值过滤器。

过滤器也需要我们自己去创建 ,他有两个参数,第一个是比较逻辑有大于,小于,大于等于,小于等于。

第二个是ByteArrayComparable类型的比较器,他有以下类型:

代码如下:

 @Test
	 public void testScanFilter() throws IOException{
		 Table table = conn.getTable(TableName.valueOf("t_1"));
		 
		 RowFilter filter1 = new RowFilter(CompareOp.GREATER, new BinaryComparator("rk004".getBytes()));
		RowFilter filter2 = new RowFilter(CompareOp.EQUAL, new BinaryPrefixComparator("rk".getBytes()));
		 FamilyFilter filter3 = new FamilyFilter(CompareOp.EQUAL, new BinaryComparator("f2".getBytes())); 
		 QualifierFilter filter4 = new QualifierFilter(CompareOp.EQUAL, new BinaryComparator("uid".getBytes()));
		     ValueFilter filter5 = new ValueFilter(CompareOp.EQUAL, new BinaryComparator("1".getBytes()));
		 Scan scan = new Scan("rk001".getBytes(),filter5);
		    ResultScanner scanner = table.getScanner(scan);
		    Iterator<Result> iterator = scanner.iterator();
		    while(iterator.hasNext()){
		    	Result next = iterator.next();
		    	printResult(next);
		    }
		    table.close();
		    conn.close();
	 }

猜你喜欢

转载自blog.csdn.net/qq_37050372/article/details/82025195
今日推荐