首先,我们通过下面这张图来深入了解通用分页
我们使用的查询dao方法等,也都是分页要使用的dao方法,什么时候使用分页呢?在查询结果是列表集,而不是下拉框等,
对分页进行封装,放进实体类
PageBean
分页三要素
page 页码 视图层传递过来
rows 页大小 视图层传递过来
total 总记录数 后台查出来
pagination 是否分页 视图层传递过来
我们将通过基本dao方法一步一步深入探究
如下案例;
package com.ly.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.ly.entity.Book;
import com.ly.util.DBAccess;
import com.ly.util.PageBean;
import com.ly.util.StringUtils;
public class BookDao {
/**
*
* @param book 是从jsp传递过来的参数封装成对象的作为参数查询并执行sql
* @param pageBean决定是否分页
* @return
* @throws SQLException
*/
public List<Book> list(Book book,PageBean pageBean) throws SQLException{
List<Book> list = new ArrayList<>();
String sql = "select * from t_mvc_book where 1=1";
if(StringUtils.isNotBlank(book.getBname())) {
sql +="and bname like '%"+book.getBname()+"%'";
}
Connection con = DBAccess.getConnection();
PreparedStatement pst = con.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while(rs.next()) {
list.add(new Book(rs.getInt("bid"),
rs.getString("bname"),
rs.getFloat("price")));
}
return list;
}
public static void main(String[] args) {
BookDao bookDao = new BookDao();
try {
Book b = new Book();
List<Book> list = bookDao.list(b, null);
for (Book book : list) {
System.out.println(book);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
我们可以基本的查询想要的资源,
但我们要的是针对 这些方法,进行改造,优化。
比如,我们在做项目期间,意味着可能以上方法可能要重复n遍,很繁琐
因此当我们知道要查什么对象,我们就知道它的属性,因此也可以动态获取。
我们来写一个通用的dao方法
目的:针对所有实体类,进行通用查询
package com.ly.util;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.ly.entity.Book;
/**
* T =book.class
* T = Student,class
* @author Administrator
*
* @param <T>
*/
public class BaseDao<T> {
/**
*
* @param sql 决定查询那张表的某些数据
* @param clz查询出来的数据封装到那个实体类中
* @param pageBean决定是否分页
* @return
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SQLException
*/
public List<T> executeQuery(String sql,Class clz,PageBean pageBean) throws InstantiationException, IllegalAccessException, SQLException{
List<T> list = new ArrayList<>();
Connection con = DBAccess.getConnection();
PreparedStatement pst = con.prepareStatement(sql);
ResultSet rs = pst.executeQuery();
while(rs.next()) {
// list.add(new Book(rs.getInt("bid"),
// rs.getString("bname"),
// rs.getFloat("price")));
/**
* 1.创建了一个Book对象
* 2.从ResultSet结果集合中获取值放入Book对象属性中
* 2.1获取到book的属性对象
* 2.2给属性对象赋值
* 3.将已经有值的book对象放入list集合中
*/
T t = (T) clz.newInstance();
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
field.set(t, rs.getObject(field.getName()));
}
list.add(t);
}
return list;
}
}
package com.ly.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.ly.entity.Book;
import com.ly.util.BaseDao;
import com.ly.util.DBAccess;
import com.ly.util.PageBean;
import com.ly.util.StringUtils;
public class BookDao extends BaseDao<Book>{
/**
*
* @param book 是从jsp传递过来的参数封装成对象的作为参数查询并执行sql
* @param pageBean决定是否分页
* @return
* @throws SQLException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public List<Book> list(Book book,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
// List<Book> list = new ArrayList<>();
String sql = "select * from t_mvc_book where 1=1";
if(StringUtils.isNotBlank(book.getBname())) {
sql +="and bname like '%"+book.getBname()+"%'";
}
return super.executeQuery(sql,Book.class, pageBean);
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
BookDao bookDao = new BookDao();
try {
Book b = new Book();
List<Book> list = bookDao.list(b, null);
for (Book book : list) {
System.out.println(book);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
同样我们达到了我们的目的。
当然我们还可以查某一特定的名
b.setBname("斗破");
我们用通用的basedao就把方法给封装了,以此类推,以后,也只需要写一个dao方法的那sql语法部分,很简洁。无论什么类
通用的分页方法:
select * from t_mvc_book where bname like ‘%斗破%’;
– 符合条件的记录数
select count(1) from (select * from t_mvc_book where bname like ‘%斗破%’) t;
–分页的查询语句
select * from t_mvc_book where bname like ‘%斗破%’ limit start,offset
start 查询数据集的起始下标
offset:查询展示在当前页的记录
package com.ly.util;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.ly.entity.Book;
/**
* T =book.class
* T = Student,class
* @author Administrator
*
* @param <T>
*/
public class BaseDao<T> {
/**
*
* @param sql 决定查询那张表的某些数据
* @param clz查询出来的数据封装到那个实体类中
* @param pageBean决定是否分页
* @return
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SQLException
*/
@SuppressWarnings("resource")
public List<T> executeQuery(String sql,Class clz,PageBean pageBean) throws InstantiationException, IllegalAccessException, SQLException{
List<T> list = new ArrayList<>();
Connection con = DBAccess.getConnection();
PreparedStatement pst = null;
ResultSet rs = null ;
try {
if (pageBean != null && pageBean.isPagination()) {
//该分页了
String countSql = getcountSql(sql);
pst = con.prepareStatement(countSql);
rs = pst.executeQuery();
if(rs.next()) {
pageBean.setTotal(rs.getLong(1)+"");
}
String pageSql = getPageSql(sql,pageBean);
pst = con.prepareStatement(pageSql);
rs = pst.executeQuery();
} else {
pst = con.prepareStatement(sql);
rs = pst.executeQuery();
}
while (rs.next()) {
// list.add(new Book(rs.getInt("bid"),
// rs.getString("bname"),
// rs.getFloat("price")));
/**
* 1.创建了一个Book对象
* 2.从ResultSet结果集合中获取值放入Book对象属性中
* 2.1获取到book的属性对象
* 2.2给属性对象赋值
* 3.将已经有值的book对象放入list集合中
*/
T t = (T) clz.newInstance();
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
field.set(t, rs.getObject(field.getName()));
}
list.add(t);
}
} finally {
DBAccess.close(con, pst, rs);
}
return list;
}
/**
* 将原生sql拼接出符合条件的某一页的数据查询sql
* @param sql
* @param pageBean
* @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) from ("+sql+") t";
}
}
查询dao方法
package com.ly.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.ly.entity.Book;
import com.ly.util.BaseDao;
import com.ly.util.DBAccess;
import com.ly.util.PageBean;
import com.ly.util.StringUtils;
public class BookDao extends BaseDao{
/**
*
* @param book 是从jsp传递过来的参数封装成对象的作为参数查询并执行sql
* @param pageBean决定是否分页
* @return
* @throws SQLException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public List list(Book book,PageBean pageBean) throws SQLException, InstantiationException, IllegalAccessException{
// List list = new ArrayList<>();
String sql = “select * from t_mvc_book where 1=1”;
if(StringUtils.isNotBlank(book.getBname())) {
sql +=" and bname like ‘%"+book.getBname()+"%’";
}
return super.executeQuery(sql,Book.class, pageBean);
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
BookDao bookDao = new BookDao();
try {
Book b = new Book();
PageBean pageBean = new PageBean();
pageBean.setPage(2);
b.setBname(“圣墟”);
List list = bookDao.list(b, pageBean);
for (Book book : list) {
System.out.println(book);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
由于代码查询的是第二页的
pageBean.setPage(2);
当然也可以选择不分页
pageBean.setPagination(false);
这里展示的就是没有分页的结果集咯
如果把以下代码去掉
pageBean.setPagination(false);
// b.setBname("圣墟");
查的就是整张数据表的所有数据
去掉这两行,就是查询数据表的前10行数据
(因为在pagebaen里面rows=10)
由此可见,我们写的通用查询方法是极大的方便了程序员们的编码,也是框架的理念。万变不离其宗而又简便,而且通用分页方法拥有同样的好处。
思路:
后台
2.1 entity
2.2 dao
第一次查满足条件的总记录数
第二次查指定页码并满足条件的记录
二次查询的条件要一致
2.3 控制层
Servlet
当然,我们也可以再写一个倒方法,继承我们的baseDao,写一个实体类,去测试,我们也可以更加深入的了解其中的乐处。
大致思路:
1、将原有的查询向上抽取
2、让返回值变成泛型
3、使用回调函数处理resultset
4、利用反射处理回调函数
5、获取总记录数(页面展示,计算总页数)
6、拼接分页sql语句,获取对应的结果集