HBase分页查询---指定PageNumber和PageSize

问题:通过指定的页码和每页记录的条数来进行分页查询。

分析问题:

要实现分页查询,因为查询的是一个范围,所以使用Scan的查询方式。然后还使用PageFilter,这样能够获取指定数量的记录。

那么问题来了,要使用scan的方式进行区间查询那么startRow是什么???

所以现在将问题转换成了求每一页的startRow !!!

当我们使用scan查询又没有指定StartRow的时候,结果是什么样的呢???

很明显,结果是从第一条记录开始的。

OK,可以确定第一页的StartRow了不是吗    这个StartRow就是 null

那么问题是不是有思路了?

通过给定的PageNumber进行循环遍历,以获取指定页的StartRow。

通过上一页的EndRow来获取当前页的StartRow。大体有两种实现方式(这两种方式根本的思路都是通过从第一页循环遍历知道获取到上一页的EndRow为止):

1、通过把上一页的最后一条记录的EndRow向后移动一点点的位置,比如上一页最后一条记录的RowKey是user_info_0001,那么将当前页的StartRow可不可以设置成user_info_00010000000000000000呢??? 这样是不是就可以查当前页的数据了,而且设置的这个RowKey和上一页最后一个RowKey非常接近,视乎不会遗漏数据。

2、当然,会有人说不怕一万就怕万一,万一要是有遗漏的数据呢?  OK,你赢了  那就使用第二种方式,我们在遍历的时候每次查询 PageSize + 1 条记录,这样每次查询的EndRow就是下一页的StartRow不是吗?   OK, 问题解决了,话不多说  直接上代码。

import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.KeyValue;
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.HTable;
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.filter.Filter;
import org.apache.hadoop.hbase.filter.PageFilter;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.Test;

public class GetDataByPage {
	private static Configuration conf = null;
	private static Connection conn = null;
	private static HTable table = null;
	private static TableName tn = null;
	private static final String ZK_CONNECT_KEY = "hbase.zookeeper.quorum";
	private static final String ZK_CONNECT_VALUE = "hadoop2:2181,hadoop3:2181,hadoop4:2181";
	
	static{
		try {
			conf = HBaseConfiguration.create();
			conf.set(ZK_CONNECT_KEY, ZK_CONNECT_VALUE);
			conn = ConnectionFactory.createConnection(conf);
			tn = TableName.valueOf("users");
			table = (HTable) conn.getTable(tn);
			
			
		} catch (Exception e) {
			System.err.println("初始化参数失败");
		}
	}
	
	@Test
	public void tests() throws Exception{
		ResultScanner pageData = null;
		pageData = getPageData(0,20);
		if(pageData != null)
			printResultScanner(pageData);
	}
	
	/**
	 * 通过传入页码数和每一页的记录条数来获取当页的数据
	 * @param page
	 * @param pagesize
	 * @return
	 * @throws Exception 
	 */
	public ResultScanner getPageData(int page, int pagesize) throws Exception{
		
		//如果每一页的记录数在少或者太多都设置为一个标准值 5
		if(pagesize < 3 || pagesize > 15) pagesize = 5;

		String startRowkey = getStartRowKey(page,pagesize);
		ResultScanner pagedate = getDate(startRowkey,pagesize);
		return pagedate;
	}
	
	/**
	 * 获取指定页的startRowKey
	 * @param page
	 * @param pagesize
	 * @return
	 * @throws Exception 
	 */
	public String getStartRowKey(int page, int pagesize) throws Exception{
		
		//如果page不标准,比如是0 或者-1那么就按照第一页处理
		if(page <= 1){
			return null;
		} else{
			//解决思路 我们每页获取pagesize+1条记录
			//每次遍历记录下最后一条记录的rowkey,就是下一页的开始rowkey
			String startRowKey = null;
			
			for (int i = 1; i < page; i++) {
				
				ResultScanner date = getDate(startRowKey,pagesize+1);
				Iterator<Result> iterator = date.iterator();
				Result next = null;
				while (iterator.hasNext()) {
					 next = iterator.next();
				}
				
				startRowKey = Bytes.toString(next.getRow());
			}
			
			return startRowKey;
		}
	}
	
	
	/**
	 * 通过pageFilter获取指定页的数据
	 * @param startRowKey
	 * @param pagesize
	 * @return
	 * @throws Exception
	 */
	public ResultScanner getDate(String startRowKey,int pagesize) throws Exception{
		
		Scan scan = new Scan();
		if(!StringUtils.isBlank(startRowKey)){
			scan.setStartRow(startRowKey.getBytes());
		}
		
		Filter pageFilter = new PageFilter(pagesize);
		
		scan.setFilter(pageFilter);
		
		ResultScanner scanner = table.getScanner(scan);
		
		return scanner;
	}
	
	/**
	 *  打印结果集
	 */
	public static void printResultScanner(ResultScanner resultScann) {
		for (Result result : resultScann) {
			printResult(result);
		}
	}
	
	public static void printResult(Result result) {
		List<Cell> cells = result.listCells();
		for (int i = 0; i < cells.size(); i++) {
			Cell cell = cells.get(i);
			printCell(cell);
		}
	}
	
	public static void printCell(Cell cell) {
		System.out.println(Bytes.toString(cell.getRow()) + "\t" + Bytes.toString(cell.getFamily()) + "\t" + Bytes.toString(cell.getQualifier())
				+ "\t" + Bytes.toString(cell.getValue()) + "\t" + cell.getTimestamp());
	}
	
	public static void printKeyValye(KeyValue kv) {
		System.out.println(Bytes.toString(kv.getRow()) + "\t" + Bytes.toString(kv.getFamily()) + "\t" + Bytes.toString(kv.getQualifier()) + "\t"
				+ Bytes.toString(kv.getValue()) + "\t" + kv.getTimestamp());
	}
	
}

 

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
hbase-client-project-2.4.16.jar是一个用于连接HBase数据库的Java客户端项目。HBase是一个分布式、面向列的NoSQL数据库,它可以存储大规模数据,并提供高可靠性和高性能的数据访问。而hbase-client-project-2.4.16.jar则是用来连接HBase数据库的Java客户端库。通过这个库,开发人员可以在Java应用中方便地访问HBase数据库,进行数据的读取、写入和管理操作。 hbase-client-project-2.4.16.jar库提供了丰富的API,使得开发人员可以编写简洁、高效的代码来操作HBase数据库。通过这个库,可以轻松地建立与HBase集群的连接,创建、删除表格,进行数据的增删改查等操作。此外,hbase-client-project-2.4.16.jar也提供了一些高级特性,比如支持过滤器、批量操作、数据版本控制等功能,让开发人员能够更加灵活地利用HBase数据库进行数据处理。 除此之外,hbase-client-project-2.4.16.jar还支持与HBase的安全认证和权限控制,可以保障数据访问的安全性。开发人员可以使用这个库来编写安全的Java应用,确保对HBase数据库的数据进行合法、受控的访问。 总之,hbase-client-project-2.4.16.jar是一个强大、灵活的Java客户端库,为开发人员提供了便捷的方式来连接、操作HBase数据库。无论是小规模的应用还是大规模的数据处理需求,它都能够满足开发人员的要求,帮助他们更有效地利用HBase数据库。 (字数: 258)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值