通用分页

–实现数据的显示(数据库连接池)、基本分页、BaseDao

通用分页核心思路
将上一次查询请求再发一次,只不过页码变了

  1. PageBean
    分页三要素
    current_page 当前页 视图层传递过来
    page_size 每页显示记录数 视图层传递过来
    total_count 总记录数 后台查出来

    pagination 是否分页 视图层传递过来

  2. 后台
    2.1 entity
    2.2 dao
    第一次查满足条件的总记录数
    第二次查指定页码并满足条件的记录
    二次查询的条件要一致
    2.3 控制层
    Servlet

  3. 视图层
    PageTag

  4. junit
    java单元测试/白盒测试
    setUp
    tearDown
    测试用例

作业

  1. mysql安装与配置/mysql卸载/继续安装与配置

  2. 使用junit4完成后台分页代码的测试

======================================

讲解数据库连接池。

  1. 分析:所有数据分页+模糊查询分页

  2. 创建项目,实现显示所有数据+模糊查询数据展示
    NewsDao:
    // 模糊查询
    String sql = “select * from news where 1=1”;
    if (StringUtils.isNotBlank(news.getNtitle())) {
    sql += " and ntitle like ‘%" + book.getNtitle().trim() + "%’";
    }

  3. 创建分页工具类PageBean,强调分页三要素。
    创建PageBean:
    // 公共参数
    private int page = 1;// 页码
    private int rows = 10;// 页大小
    private int total = 0;// 总记录数
    private boolean pagination = true;// 是否分页

    ……

    /**

    • 获得起始记录的下标
      */
      public int getStartIndex() {
      return (this.page - 1) * this.rows;
      }
  4. 将2与3步结合实现分页(但不是通用分页,要针对所有的表)。
    4.1 创建BaseDao,编写查全部,支持分页的方法:
    public List executeQuery(String sql, PageBean pageBean),将查询的代码复制过来。

     这里需要完成两个操作:
     (1)第一次查满足条件的总记录数
     	if (null != pageBean && pageBean.isPagination()) {
     		String countSql = this.getCountSql(sql);  //4.2 对SQL进行处理
     		System.out.println("countSql:" + countSql);
     		pstmt = conn.prepareStatement(countSql);
     		rs = pstmt.executeQuery();
     		if (rs.next()) {
     			// 兼容Long/Integer两种类型
     			Object total = rs.getObject(1);
     			pageBean.setTotal(total.toString());
     		}
     		DBAccess.close(null, pstmt, rs);
     	}
    
    
     	(2)第二次查指定页码并满足条件的记录
     	if (null != pageBean && pageBean.isPagination()) {
     		sql = this.getPageSql(sql, pageBean);
     	}
    
     	System.out.println("sql:" + sql);
     	pstmt = conn.prepareStatement(sql);
     	rs = pstmt.executeQuery();
     	return callback.foreach(rs);   //5. ResultSet回调接口的实现
    

    4.2 对SQL进行处理:将普通的sql转换成查总记录数的getCountRows()
    SQL语句:select count(*) from ( select * from news where 1=1 ntitle like ‘%1%’ ) t1;

     private String getCountSql(String sql){
     	return "select count(*) from ("+sql+") t1";
     }
    

    4.3 对SQL进行处理:求总页数的方法getPageSql()

     private String getPageSql(String sql, PageBean pageBean){
     	return sql+" limit "+pageBean.getStartIndex()+","+pageBean.getRows();
     }
    
     //在pageBean中创建获得起始记录的下标的方法:getStartIndex()
    
  5. ResultSet回调接口的实现
    5.1 在BaseDao类中创建一内部接口
    // 专门遍历ResultSet的回调接口
    public static interface CallBack {
    public List foreach(ResultSet rs) throws SQLException;
    }

    5.1 创建一NewsImpl类,实现BaseDao.CallBack接口
    重写foreach方法,将接收到的rs对象转换成List集合。

  6. 修改NewsDao
    6.1 修改list方法
    public List list(News news, PageBean pageBean) {
    // 模糊查询
    String sql = “select * from news where 1=1”;
    if (StringUtils.isNotBlank(news.getNtitle())) {
    sql += " and ntitle like ‘%" + news.getNtitle().trim() + "%’";
    }
    // System.out.println(sql);

     return this.executeQuery(sql, pageBean, new BaseDAO.Callback<News>() {
     	@Override
     	public List<News> foreach(ResultSet rs) throws SQLException {
     		List<News> newsList = new ArrayList<News>();
     		News b = null;
     		while (rs.next()) {
     			b = new News();
     			b.setNId(rs.getInt("nid"));
     			b.setNtitle(rs.getString("ntitle"));
     			b.setNauthor(rs.getFloat("nauthor));
    
     			newsList.add(b);
     		}
     		return newsList;
     	}
     });
    

    }

    6.2 在test测试类中:
    private BookDAO bookDAO = new BookDAO();
    private Book book;

     @Before
     public void setUp() throws Exception {
     	book = new Book();
     }
    
     @Test
     public void testList(){
     	PageBean pageBean = new PageBean();
     	pageBean.setPagination(true); //要进行分页
     	news.setNtitle("新");	//查询新闻标题中的“新”
    
     	List<Object> newsList = newsDao.list(news, pageBean);
     	for(News n : newsList){
     		System.out.println(b);
     	}
    
     }
    
  7. 主要视图层:
    7.1 创建好前端JSP页面
    7.2 解决两个问题:
    (1)如何将上一次查询请求再发一次
    第1:获得上次的请求
    第2:获得上次的参数key

     (2)
    
     操作:
     创建NewsServlet类,重写doGet和doPost。
     在doPost()中:
     	//第1:获得上次的请求
     	String contextPath = req.getContextPath()
     	String url = req.getServletPath(); //获得上次请求的地址
    
     	//第2:获得上次的参数key  -> Map("key",value)
     	Map<String, String[]> parameterMap = req.getParamterMap();  //获得请求中的所有参数
     
     	再点分页链接时,再发一次请求。
    

    7.3 在PageBean中添加两属性:
    private String url; //根目录+请求地址
    private Map<String,String[]> paramerMap;//请求参数
    //封装

     //写个方法setReques
    

    /**

    • 对PageBean属性进行初始化设置
    • @param request
      */
      public void setRequest(HttpServletRequest request) {
      //获值
      String page = request.getParameter(“page”);
      String rows = request.getParameter(“rows”);
      String pagination = request.getParameter(“pagination”);
      //设置值
      this.setPage(page);
      this.setRows(rows);
      this.setPagination(pagination);
      //提交路径及参数(将上一次查询请求再发一次,只不过页码变了)
      this.url = request.getContextPath() + request.getServletPath();
      this.parameterMap = request.getParameterMap();

    }

  8. 创建PageTag类,做自定义JSP标签
    第一步:创建PageTag类,继承BodyTagSupport。
    第二步:封装PageBean属性(因为得到PageBean对象,就能得到分页的元素)
    第三步:重写doStartTag()方法,向JSP页面输入
    JspWriter out = pageContext.getOut();
    out.println(this.toHTML());
    return SKIP_BODY;
    第四步:编写toHTML()方法,返回拼接的String。

====================================================================

News.java

NewsDao.java
extends BaseDAO

//通用分页查询
public List<Book> list(Book book, PageBean pageBean) {
	// 模糊查询
	String sql = "select * from t_book where 1=1";
	if (StringUtils.isNotBlank(book.getBookName())) {
		sql += " and book_name like '%" + book.getBookName().trim() + "%'";
	}
	// System.out.println(sql);

	return this.executeQuery(sql, pageBean, new BaseDAO.Callback<Book>() {
		@Override
		public List<Book> foreach(ResultSet rs) throws SQLException {
			List<Book> bookList = new ArrayList<Book>();
			Book b = null;
			while (rs.next()) {
				b = new Book();
				b.setBookId(rs.getInt("book_id"));
				b.setBookName(rs.getString("book_name"));
				b.setPrice(rs.getFloat("price"));

				bookList.add(b);
			}
			return bookList;
		}
	});
}

BaseDao.java
//专门遍历ResultSet的回调接口
public static interface Callback {
public List foreach(ResultSet rs) throws SQLException;
}

//查全部,支持分页
public List<K> executeQuery(String sql, PageBean pageBean, Callback<K> callback) {
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
		conn = DBAccess.getConnection();

		// 第一次查满足条件的总记录数
		if (null != pageBean && pageBean.isPagination()) {
			String countSql = this.getCountSql(sql);
			System.out.println("countSql:" + countSql);
			pstmt = conn.prepareStatement(countSql);
			rs = pstmt.executeQuery();
			if (rs.next()) {
				// 兼容Long/Integer两种类型
				Object total = rs.getObject(1);
				pageBean.setTotal(total.toString());
			}
			DBAccess.close(null, pstmt, rs);
		}

		// 第二次查指定页码并满足条件的记录
		if (null != pageBean && pageBean.isPagination()) {
			sql = this.getPageSql(sql, pageBean);
		}
		System.out.println("sql:" + sql);
		pstmt = conn.prepareStatement(sql);
		rs = pstmt.executeQuery();
		return callback.foreach(rs);
	} catch (Exception e) {
		throw new RuntimeException(e);
	} finally {
		DBAccess.close(conn, pstmt, rs);
	}
}

//将普通的sql转换成查总记录数的sql
private String getCountSql(String sql) {
	String countSql = "select count(*) from (" + sql + ") t1";
	return countSql;
}

//将普通的sql转换支持分页的sql
private String getPageSql(String sql, PageBean pageBean) {
	String pageSql = sql + " limit " + pageBean.getStartIndex() + "," + pageBean.getRows();
	return pageSql;
}

PageBean.java
分页封装

泛型
匿名内部类

将上一次数据再发一次
实现将四个参数显示在页面上

写自定义标签Tag
将四个参数转换成按钮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值