–实现数据的显示(数据库连接池)、基本分页、BaseDao
通用分页核心思路
将上一次查询请求再发一次,只不过页码变了
-
PageBean
分页三要素
current_page 当前页 视图层传递过来
page_size 每页显示记录数 视图层传递过来
total_count 总记录数 后台查出来pagination 是否分页 视图层传递过来
-
后台
2.1 entity
2.2 dao
第一次查满足条件的总记录数
第二次查指定页码并满足条件的记录
二次查询的条件要一致
2.3 控制层
Servlet -
视图层
PageTag -
junit
java单元测试/白盒测试
setUp
tearDown
测试用例
作业
-
mysql安装与配置/mysql卸载/继续安装与配置
-
使用junit4完成后台分页代码的测试
======================================
讲解数据库连接池。
-
分析:所有数据分页+模糊查询分页
-
创建项目,实现显示所有数据+模糊查询数据展示
NewsDao:
// 模糊查询
String sql = “select * from news where 1=1”;
if (StringUtils.isNotBlank(news.getNtitle())) {
sql += " and ntitle like ‘%" + book.getNtitle().trim() + "%’";
} -
创建分页工具类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;
}
- 获得起始记录的下标
-
将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()
-
ResultSet回调接口的实现
5.1 在BaseDao类中创建一内部接口
// 专门遍历ResultSet的回调接口
public static interface CallBack {
public List foreach(ResultSet rs) throws SQLException;
}5.1 创建一NewsImpl类,实现BaseDao.CallBack接口
重写foreach方法,将接收到的rs对象转换成List集合。 -
修改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.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();
}
-
创建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
将四个参数转换成按钮