JAVA学习之 实现分页查询

         分页是系统中常用到的功能 , 只要涉及到查询必定伴随而来的就是分页 , 之前也学习过关于分页的内容,例如在牛腩的新闻发布系统,之前学习的大部分都是使用了假分页,这次学习 java ,使用 Oracle 数据库来实现一下真分页。

       首先来说一下实现这个分页查询的流程:

一、封装分页信息:

         需要分页的部分我们首先要做的是为分页封装一个分页实体,方便返回查询信息,封装如下:

/**
 *封装分页信息
 * @author YoungJong
 *
 */
public class PageModel<E> {
	//结果集
	private List<E> list;
	//查询记录数
	private int totalRecords;
	//每页多少条记录
	private int pageSize;
	//第几页
	private int pageNo;
	
	public List<E> getList() {
		return list;
	}
	public void setList(List<E> list) {
		this.list = list;
	}
	public int getTotalRecords() {
		return totalRecords;
	}
	public void setTotalRecords(int totalRecords) {
		this.totalRecords = totalRecords;
	}
	public int getPageSize() {
		return pageSize;
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	public int getPageNo() {
		return pageNo;
	}
	public void setPageNo(int pageNo) {
		this.pageNo = pageNo;
	}
	/**
	 * 总页数
	 * @return
	 */
	public int getTotalPages(){
		return(totalRecords+pageSize-1)/pageSize;
		
	}
	/**
	 * 取得首页
	 * @return
	 */
	public int getTopPageNo(){
		return 1;
	}
	/**
	 * 上一页
	 * @return
	 */
	public int getPreviousPageNo(){
		if(pageNo<=1){
			return 1;
		}
		return pageNo-1;
	}
	/**
	 * 下一页
	 * @return
	 */
	public int getNextPageNo() {
		if (pageNo >= getBottomPageNo()) {
			return getBottomPageNo();
		}
		return pageNo + 1;	
	}
	/**
	 * 取得尾页
	 * @return
	 */
	public int getBottomPageNo(){
		return getTotalPages();
	}

}

       这里的重点是这个实体使用了泛型,使用分页显示的数据并不全是同一种实体数据,为了更好的复用分页查询,将结果集定义成泛型,则便于众多信息的查询:

二、页面加载显示查询数据并分页显示( Servlet ):

         页面加载时调用一个 Servlet ,通过 Servelt 来调用分页查询并将查询结果返回到页面:我们先来看 Servlet 的代码实现:

public class SearchItemServlet extends AbstractItemServlet {
	/**
	 * 覆盖servlet的doGet方法
	 */
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// 定义显示第几页的变量
		int pageNo=0;
		//int pageSize=2;
		//从配置文件读取每页设置的显示数据数量
		int pageSize=Integer.parseInt(this.getServletContext().getInitParameter("page-size"));
		//获取jsp传递过来的显示第几页
		String pageNoString=req.getParameter("pageNo");
		//如果为空则显示第一页
		if(pageNoString==null){
			pageNo=1;
		}else{
			pageNo=Integer.parseInt(pageNoString);
		}
		
		//取得查询条件条件,条件为空则查询全部
		String condation=req.getParameter("clientIdOrName");
		
		//调用分页查询方法,返回查询数据
		PageModel pageModel=itemManager.findItemList(pageNo, pageSize, condation);
		
		///取得查询页面传递过来的分页实体
		req.setAttribute("pageModel", pageModel);
		//将查询数据在页面显示
	    req.getRequestDispatcher("/basedata/item_maint.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		//super.doPost(req, resp);
		doGet(req,resp);
	}

}

其中值得注意的是,关于每页显示数据条数的问题,这一部分可以自己写在代码里,也可以将显示的数目写在配置文件中,只需要读取配置文件即可,方便配置:

其中配置文件可以这样写:在 WEB-INF 下的 web.xml 中:

<context-param>
		<param-name>page-size</param-name>
		<param-value>3</param-value>
</context-param>

这种写法是可以适用于系统中所有的 Servlet 的,每一个想读取页面显示数量的都可以进行读取。

三、 Dao 层实现分页查询:

       Servlet 调用查询方法是通过一个 Manager 的接口,类似于三层中 B 层的作用,由于没有复杂的逻辑,所以这里的代码很简单:

/**
* 查询物料信息,参数分别为:页码,每页显示数据,查询条件
	 */
	public PageModel findItemList(int pageNo, int pageSize, String condation) {
		
		Connection conn=null;
		try{
			conn=DbUtil.getConnection();
			//调用Dao层的分页查询
			return itemDao.findItemList(conn, pageNo, pageSize, condation);
		}finally{
			DbUtil.close(conn);
		}
		
	}

真分页查询的重点在于 DAO 层的实现,下面我们来看一下代码:

/**
* 分页查询
	 */
	public PageModel findItemList(Connection conn,int pageNo, int pageSize, String condation) {
		
		StringBuffer sbSql=new StringBuffer();
		
		sbSql.append("select * ")
		.append("from (")
			.append("select i.*, rownum rn from (")
			.append("select a.item_no, a.item_name, a.spec, a.pattern, a.item_category_id, ")
			.append("b.name as item_category_name, a.item_unit_id, c.name as item_unit_name, a.file_name ")
			.append("from t_items a, t_data_dict b, t_data_dict c ")
			.append("where a.item_category_id=b.id and a.item_unit_id=c.id  ");
			if (condation != null && !"".equals(condation)) {
				sbSql.append(" and (a.item_no like '" + condation + "%' or a.item_name like '" + condation + "%') ");
			}
			sbSql.append(" order by a.item_no")
			.append(") i where rownum<=? ")
			.append(") ")
			.append("where rn >? ");
	System.out.println("sql=" + sbSql.toString());
			
	//通常采用日志组件记录,如log4j, 级别:info,debug,error...
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	PageModel pageModel = null;
	try {
		//为查询条件参数赋值
		pstmt = conn.prepareStatement(sbSql.toString());
		//查询数据库中列在如何条件之间的数据
		pstmt.setInt(1, pageNo * pageSize);
		pstmt.setInt(2, (pageNo - 1) * pageSize);
		int i=pageNo*pageSize;
		int j=(pageNo - 1) * pageSize;
		rs = pstmt.executeQuery();
		//获得符合条件的信息结婚
		List itemList = new ArrayList();
		while (rs.next()) {
			Item item = new Item();
			item.setItemNo(rs.getString("item_no"));
			item.setItemName(rs.getString("item_name"));
			item.setSpec(rs.getString("spec"));
			item.setPattern(rs.getString("pattern"));
			//构造ItemCategory
			ItemCategory ic = new ItemCategory();
			ic.setId(rs.getString("item_category_id"));
			ic.setName(rs.getString("item_category_name"));
			item.setItemCategory(ic);
			
			//构造ItemUnit
			ItemUnit iu = new ItemUnit();
			iu.setId(rs.getString("item_unit_id"));
			iu.setName(rs.getString("item_unit_name"));
			item.setItemUnit(iu);
			
			item.setFileName(rs.getString("file_name"));
			itemList.add(item);
		}
		//为分页实体赋值
		pageModel = new PageModel();
		pageModel.setPageNo(pageNo);
		pageModel.setPageSize(pageSize);
		pageModel.setList(itemList);
		//根据条件取得记录数
		int totalRecords = getTotalRecords(conn, condation);
		pageModel.setTotalRecords(totalRecords);
	}catch(SQLException e) {
		e.printStackTrace();
		//记录到日志文件 error
		throw new ApplicationException("分页查询失败");
	}finally {
		DbUtil.close(rs);
		DbUtil.close(pstmt);
	}
	return pageModel;
	}

其实看起来复杂,做起来逻辑并不复杂,很容易实现

四、 jsp 页面显示

    后台获得了数据,传递到页面,页面接收后就可以在页面上进行显示了,其实获得数据的代码一句话就可以搞定:更 Servlet 的代码是对应的,因为在 Servlet 中我们已经使用了 setAttribute ,所以 jsp 中的代码如下:

PageModel pageModel= (PageModel) request.getAttribute("pageModel");

点击跳到首页的方法如下(其他跳转类似不一一列出):

//跳转到首页
function topPage() {
	
		window.self.location="<%=basePath%>servlet/item/SearchItemServlet?pageNo=<%=pageModel.getTopPageNo()%>&clientIdOrName=<%=clientIdOrName%>";

}
     这是一个完整的分页查询的流程,很多都是封装好的可以复用,只是在 DAO 层的查询语句需要自己写,不过最近了解了一些 NHiernate ,关于 Hibernate 的知识也在学习中,自己要写 sql 语句的问题也是可以解决的!
我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章