目录
一,PageBean
二,反射通用后台查询方法
三,通用的分页后台查询方法
四,junit4
前言:通用分页的原意义:能够简化分页相关功能的开发
目的:极大优化代码
分页代码比较:
原有的分页代码:
1.存在大量重复分页条的HTML代码
2.将上一次的查询条件带到下一次,隐藏的from表单HTML
3.后台有大量的代码是重复的1.按原始方式写一个查询
存在问题:①有重复代码
②分页参数不清晰
解决方案:①baseDao ②pagebean2.BaseDao
存在问题:
不同人调用,处理resultset方式是不一样的解决方案:通过回调函数解决 callback
3.callback
4.通用分页
原始SQL:调用方拼装好的sql
分页sql:页面要展示数据的sql,第N也的数据
符合条件的总记录数sql:时为了拿到总录数,计算总页数
首先把该有的文件放到util包里面
<如图所示>
分析:DBAccess为数据库辅助类
EncodingFiter为中文乱码处理
PageBean为分页的工具类
StringUtils为判空
1.为什么封装
方便使用
2.封装的优点
精简代码
《代码演示》
package com.dengxiyan.util;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
public PageBean() {
super();
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public void setTotal(String total) {
this.total = Integer.parseInt(total);
}
public boolean isPagination() {
return pagination;
}
public void setPagination(boolean pagination) {
this.pagination = pagination;
}
/**
* 获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
}
}
《代码演示》
BaseDao反射类
package com.dengxiyan.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import com.dengxiyan.entity.Book;
/**
* T代表的是实体类,可以是book/user/...
* @author DXY
*
* @param 2022年6月21日下午7:31:26
*/
public class BaseDao {
/*public List executeQuery(String sql,PageBean pageBean,CallBack callBack) throws Exception{
// SELECT * FROM 'tb_book' WHERE bname like '%哈哈哈%';
//从上面得到SELECT COUNT(1) as n FROM (SELECT * FROM tb_book WHERE bname LIKE '%哈哈哈%') t;
//目的是为了得到总记录数---->总目的是得到总页数
*//**
* 1.拿到数据库连接
* 2.拿到preparstatement
* 3.执行sql语句
*//*
Connection con = DBAccess.getConnection();//重复代码1
PreparedStatement ps = con.prepareStatement(sql);//重复代码2
ResultSet rs = ps.executeQuery();//重复代码3
while(rs.next()) {
ls.add(new Book(rs.getInt(bid),rs.getString("bname"),rs.getFloat("price")));
}
//查询不同的表,必然要处理不同的结果集
//接口是调用方实现
return callBack.foreach(rs);
}*/
public List executeQuery(String sql,PageBean pageBean,CallBack callBack) throws Exception{
// SELECT * FROM 'tb_book' WHERE bname like '%哈哈哈%';
//从上面得到SELECT COUNT(1) as n FROM (SELECT * FROM tb_book WHERE bname LIKE '%哈哈哈%') t;
//目的是为了得到总记录数---->总目的是得到总页数
/**
* 1.拿到数据库连接
* 2.拿到preparstatement
* 3.执行sql语句
*/
Connection con = null;//重复代码1
PreparedStatement ps = null;//重复代码2
ResultSet rs = null;//重复代码3
if(pageBean !=null && pageBean.isPagination()) {
String countSql = getCountSql(sql);
con = DBAccess.getConnection();//重复代码1
ps = con.prepareStatement(countSql);//重复代码2
rs = ps.executeQuery();//重复代码3
if(rs.next()) {
//因为下面Sql语句里有个n 将n放进以下代码
//pageBean(当前实体类)就包含了总记录数
pageBean.setTotal(rs.getString("n"));
}
String pageSql = getpageSql(sql,pageBean);
con = DBAccess.getConnection();//重复代码1
ps = con.prepareStatement(pageSql);//重复代码2
rs = ps.executeQuery();//重复代码3
}
else {
con = DBAccess.getConnection();//重复代码1
ps = con.prepareStatement(sql);//重复代码2
rs = ps.executeQuery();//重复代码3
}
return callBack.foreach(rs);
}
/**
* 拼装第n页的数据的sql
* @return
*/
private String getpageSql(String sql,PageBean pageBean) {
// TODO Auto-generated method stub
return sql + " limit "+pageBean.getStartIndex() + ","+pageBean.getRows();
}
/**
* 拼装符合条件总记录数的sql
* @param sql
* @return
*/
private String getCountSql(String sql) {
// TODO Auto-generated method stub
return "select count(1) as n from ("+sql+") t";
}
}
在实体类的数据访问层继承BaseDao(反射类)
《代码演示》
代码分析:
如果没有bname的值,此处的sql语句也没条件,执行时固然会报错,所以以上sql语句要加where 1=1
sql += " and bid =" +bid;
所以下面的这条sql语句要加上where 1=1 ,这样不管放哪个条件都不会报错
String sql = "select * from tb_book where 1=1 ";
package com.dengxiyan.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import com.dengxiyan.entity.Book;
import com.dengxiyan.util.BaseDao;
import com.dengxiyan.util.DBAccess;
import com.dengxiyan.util.PageBean;
import com.dengxiyan.util.StringUtils;
public class BookDao extends BaseDao{
/**
* 以前阶段版本
* @param book
* @param pageBean
* @return
* @throws Exception
*/
public List list(Book book,PageBean pageBean) throws Exception{
List list = new ArrayList();
/**
* 1.拿到数据库连接
* 2.拿到preparstatement
* 3.执行sql语句
*/
Connection con = DBAccess.getConnection();//重复代码1
String sql = "select * from tb_book where 1=1 ";
String bname = book.getBname();
//isNotBlank(bname)不为空
if(StringUtils.isNotBlank(bname)) {
sql +=" and bname like '%"+bname+"%'";
}
int bid = book.getBid();
//int类型的默认值为0
if(bid!=0) {
sql += " and bid =" +bid;
}
PreparedStatement ps = con.prepareStatement(sql);//重复代码2
ResultSet rs = ps.executeQuery();//重复代码3
while(rs.next()) {
list.add(new Book(rs.getInt(bid),rs.getString("bname"),rs.getFloat("price")));
}
return list;
}
/**
* 后期阶段第一版本
* @param book
* @param pageBean
* @return
* @throws Exception
*/
public List list2(Book book,PageBean pageBean) throws Exception{
List ls = new ArrayList();
/**
* 1.拿到数据库连接
* 2.拿到preparstatement
* 3.执行sql语句
*/
String sql = "select * from tb_book where 1=1 ";
String bname = book.getBname();
if(StringUtils.isNotBlank(bname)) {
sql +=" and bname like '%"+bname+"%'";
}
int bid = book.getBid();
if(bid!=0) {
sql += " and bid =" +bid;
}
TreeSet treeSet = new TreeSet((x,y)->{
return x.compareTo(y);
});
/**
* 简单方式
*/
return super.executeQuery(sql, pageBean, rs ->{
List list = new ArrayList();
try {
while(rs.next()) {
ls.add(new Book(rs.getInt(bid),rs.getString("bname"),rs.getFloat("price")));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
});
}
//增删改查junit
// public static void main(String[] args) throws Exception {
// List list = new BookDao().list(new Book(), null);
// for (Book book : list) {
// System.out.println(book);
// }
// }
}
《效果图》
前期编码版本效果图
《代码演示》
package com.dengxiyan.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import com.dengxiyan.entity.Book;
/**
* T代表的是实体类,可以是book/user/...
* @author DXY
*
* @param 2022年6月21日下午7:31:26
*/
public class BaseDao {
public List executeQuery(String sql,PageBean pageBean,CallBack callBack) throws Exception{
// SELECT * FROM 'tb_book' WHERE bname like '%哈哈哈%';
//从上面得到SELECT COUNT(1) as n FROM (SELECT * FROM tb_book WHERE bname LIKE '%哈哈哈%') t;
//目的是为了得到总记录数---->总目的是得到总页数
/**
* 1.拿到数据库连接
* 2.拿到preparstatement
* 3.执行sql语句
*/
Connection con = null;//重复代码1
PreparedStatement ps = null;//重复代码2
ResultSet rs = null;//重复代码3
if(pageBean !=null && pageBean.isPagination()) {
String countSql = getCountSql(sql);
con = DBAccess.getConnection();//重复代码1
ps = con.prepareStatement(countSql);//重复代码2
rs = ps.executeQuery();//重复代码3
if(rs.next()) {
//因为下面Sql语句里有个n 将n放进以下代码
//pageBean(当前实体类)就包含了总记录数
pageBean.setTotal(rs.getString("n"));
}
String pageSql = getpageSql(sql,pageBean);
con = DBAccess.getConnection();//重复代码1
ps = con.prepareStatement(pageSql);//重复代码2
rs = ps.executeQuery();//重复代码3
}
else {
con = DBAccess.getConnection();//重复代码1
ps = con.prepareStatement(sql);//重复代码2
rs = ps.executeQuery();//重复代码3
}
return callBack.foreach(rs);
}
/**
* 拼装第n页的数据的sql
* @return
*/
private String getpageSql(String sql,PageBean pageBean) {
// TODO Auto-generated method stub
return sql + " limit "+pageBean.getStartIndex() + ","+pageBean.getRows();
}
/**
* 拼装符合条件总记录数的sql
* @param sql
* @return
*/
private String getCountSql(String sql) {
// TODO Auto-generated method stub
return "select count(1) as n from ("+sql+") t";
}
}
《效果图》
就相当于一个测试类
创建方式如下:
勾选 Junit4
根据实际情况勾选
《代码演示》
package com.dengxiyan.dao;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.dengxiyan.entity.Book;
import com.dengxiyan.util.PageBean;
/**
* 作用:
* 能够针对单个方法进行测试,相对于main方法而言,测试耦合性降低了
* @author DXY
*2022年6月21日下午7:25:52
*/
public class BookDaoTest {
/**
* 调用以下两个方法与 @Before @After这两个注解有关,与方法名无关
* @throws Exception
*/
@Before
public void setUp() throws Exception {
System.out.println("被测试方法执行之前调用");
}
@After
public void tearDown() throws Exception {
System.out.println("被测试方法执行之后调用");
}
@Test
public void testList() {
List ls;
try {
ls = new BookDao().list(new Book(), null);
for (Book book : ls) {
System.out.println(book);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void testList2() {
List ls;
try {
ls = new BookDao().list2(new Book(), null);
for (Book book : ls) {
System.out.println(book);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("测试代码2");
}
public void testList3() {
List ls;
try {
Book b = new Book();
//加条件
b.setBname("圣墟");
PageBean pageBean = new PageBean();
pageBean.setPage(3);
pageBean.setRows(20);
ls = new BookDao().list2(b, pageBean);
for (Book book : ls) {
System.out.println(book);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("测试代码2");
}
}
《运行效果图》