2、简单查询功能
①建立数据库连接
②预定义对象PrepareStatement
③查询结果集
④处理结果集
public List list(Book book) throws Exception{
List books=new ArrayList();
String sql=“select * from t_mvc_book where 1=1”;
// 书籍名称
String bname=book.getBname();
// 书籍名称模糊查询 不死不灭最终是前台jsp页面传递过来的
if(StringUtils.isNotBlank(bname)) {
sql+=" and bname like ‘%“+bname+”%’";
}
Connection con=DBAccess.getConnection();
PreparedStatement pst=con.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
while(rs.next()) {
books.add(new Book(rs.getInt(“bid”), rs.getString(“bname”), rs.getFloat(“price”)));
}
return books;
}
不足之处:
①以上三步需要重复(建立数据库连接,2、预定义对象PrepareStatement,查询结果集);
②都是要返回数据库表对应的集合,集合中的对象都是不同的
③都是要处理结果集ResultSet rs
④ 代码不一样,具体体现在,不同表会有不同的字段,那么实体类对应的属性就会不一样
总结:需要写大量的重复代码,系统中的查询功能越多,重复代码量越大
提供解决方案(也就是通用查询方法,下面的知识点):
①抽取变量部分作为参数:sql、Class对象(book.class,article.class)
②抽取公共的父类,把重复性的代码剥离出来
3、通用查询功能
公共的父类:BaseDao,把重复性的代码剥离出来,供其他的使用
package lv.com.dao;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import lv.com.entity.Book;
import lv.com.util.DBAccess;
import lv.com.util.StringUtils;
/**
* 所以Dao层(BookDao,UserDao)的父类
* @author T440s
*
* @param
*/
public class BaseDao {
public List list(String sql,Class clz) throws Exception{
// 不确定list集合中装了什么 子类Dao继承BaseDao,子类传递什么类.class,那么list集合中放的就是什么
List list=new ArrayList();
Connection con=DBAccess.getConnection();
PreparedStatement pst=con.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
while(rs.next()) {
// books.add(new Book(rs.getInt(“bid”), rs.getString(“bname”), rs.getFloat(“price”)));
/**
* 分析:
* 1、实例化了一个对象
* 2、从ResultSet的对象的属性获取值(bid),赋值给了前面的实例化的对象
* 3、把已经赋值了的对象,添加到list集合中
*/
// Book book=new Book();
T t = clz.newInstance();
// 2、从ResultSet的对象的属性获取值(bid),赋值给了前面的实例化的对象
// b.setBid(rs.getInt(“bid”));
Field[] fields = clz.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
f.set(t, rs.getObject(f.getName()));
}
// 3、把已经赋值了的对象,添加到list集合中
list.add(t);
}
return list;
}
}
继承公共的父类,减少了代码:
public class BookDao extends BaseDao{
public List list2(Book book) throws Exception{
String sql=“select * from t_mvc_book where 1=1”;
// 书籍名称
String bname=book.getBname();
// 书籍名称模糊查询 不死不灭最终是前台jsp页面传递过来的
if(StringUtils.isNotBlank(bname)) {
sql+=" and bname like ‘%“+bname+”%’";
}
return super.list(sql, Book.class);
}
}
public class ActicleDao extends BaseDao{
public List list(Acticle acticle) throws Exception{
return super.list(“select * from t_jsoup_article”, Acticle.class);
}
}
实行:
public static void main(String[] args) throws Exception{
BookDao bd=new BookDao();
Book book=new Book();
book.setBname(“不死不灭”);
// List list=bd.list(book);
List list=bd.list2(book);
for(Book b:list) {
System.out.println(b);
}
查询结果:
4、分页查询
目标:
想要做一个通用的分页查询,子类去继承父类,自带了分页功能,并且代码量极少;
最终当碰到分页的需求的时候,只要写少量代码。
分页通常有关键的因素:
第page页、显示数目(rows)、符合查询条件的总记录数(total)。
共N页的算法:total%rows==0?total/rows:total/rows+1;
①MySQL分页
mysql分页是通过limit关键字,分页数据库sql格式:
总记录数查询:
select count(1) from (select * from t_mvc_book where bname like ‘%圣墟%’)t
select * from 表名 limit 起始下标, 展示数目(rows)
原sql查询:sql=select * from t_mvc_book where like ‘%圣墟%’
分页sql: pageSql=sql limit (page-1)*rows,rows
总记录数:countSql=select count(1) from (sql) t
②、编码思路
原来list集合中返回的是符合条件的所有数据,现在需要发挥第page页的数据,那么就意味着sql要加工成pageSql;
需要分页,那么要求符合条件的总记录数,保存到PageBean中
公共的父类分页:
// 通用分页查询
/**
* 是否需要分页:
*无需分页(项目中的下拉框,查询条件教员下拉框)
*必须分页(项目中列表类需求,订单列表、商品列表、学生列表……)
* */
public List executeQuery(String sql,Class clz,PageBean pageBean) throws Exception{
List list=new ArrayList();
Connection con=DBAccess.getConnection();
PreparedStatement pst=con.prepareStatement(sql);
ResultSet rs=pst.executeQuery();
if(pageBean !=null&&pageBean.isPagination()) {
// 必须分页(列表需求)
String countSQL=getCountSQL(sql);
pst=con.prepareStatement(countSQL);
rs=pst.executeQuery();
if(rs.next()) {
pageBean.setTotal(String.valueOf(rs.getObject(1)));
}
// 最后才处理返回的结果集
String pageSQL=getPageSQL(sql,pageBean);//符合条件的某一页数据
pst=con.prepareStatement(pageSQL);
rs=pst.executeQuery();
}else {
// 不分页(select需求)
pst=con.prepareStatement(sql);//符合条件的所有数据
rs=pst.executeQuery();
}
while(rs.next()) {
T t = clz.newInstance();
Field[] fields = clz.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
f.set(t, rs.getObject(f.getName()));
}
list.add(t);
}
return list;
}
/**
* 将原生SQL转换成符合条件的总记录数CountSQL
* @param sql
* @return
*/
private String getCountSQL(String sql) {
return “select count(1) from (”+sql+“)t”;
}
/**
* 原生SQL转换成pageSQL
* @param sql
* @param pageBean
* @return
*/
private String getPageSQL(String sql,PageBean pageBean) {
// TODO Auto-generated method stub
return sql +" limit “+ pageBean.getStartIndex() +”,"+pageBean.getRows();
}
调用方法:
public List list3(Book book,PageBean pageBean) throws Exception{
String sql=“select * from t_mvc_book where 1=1”;
// 书籍名称
String bname=book.getBname();
// 书籍名称模糊查询 不死不灭最终是前台jsp页面传递过来的
if(StringUtils.isNotBlank(bname)) {
sql+=" and bname like ‘%“+bname+”%’";
}
return super.executeQuery(sql, Book.class,pageBean);
}
执行:
public static void main(String[] args) throws Exception{
BookDao bd=new BookDao();
Book book=new Book();
book.setBname(“不死不灭”);
// List list=bd.list(book);
// List list=bd.list2(book);
PageBean pageBean=new PageBean();
// 查第二页的数据,模拟从jsp传递页码2到后台
// pageBean.setPage(2);
// 项目开发中,下拉框的需求,不分页,模拟jsp传递不分页的信息pageination=false
pageBean.setPagination(false);
List list=bd.list3(book,pageBean);
for(Book b:list) {
System.out.println(b);
}
}
二、通用前台分页
分析:
1、前台分页,后一次请求相较于上一次,只不过是页码改变了
1、1需要保存上一次请求的URL
1、2需要保存上一次请求的参数 bname、price
1、3需要保存上一次请求的分页设置 pagination
1、4需要保存上一次请求的展示条目数
1、5初始化请求的页码page
PageBean类:
package lv.com.util;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 页码
private int rows = 10;// 页大小
private int total = 0;// 总记录数
private boolean pagination = true;// 是否分页
private String url;//保存上一次请求的url
private Map<String, String[]> paraMap=new HashMap<>();//保存上一次请求的数组
/**
* 初始化pagebean的,保存上一次请求的重要参数
* @param req
*/
public void setRequest(HttpServletRequest req) {
// 1、1需要保存上一次请求的URL
this.setUrl(req.getRequestURI().toString());
// 1、2需要保存上一次请求的参数 bname、price
this.setParaMap(req.getParameterMap());
// 1、3需要保存上一次请求的分页设置 pagination
this.setPagination(req.getParameter(“pagination”));
// 1、4需要保存上一次请求的展示条目数
this.setRows(req.getParameter(“rows”));
// 1、5初始化请求的页码page
this.setPage(req.getParameter(“page”));
}
public void setPage(String page) {
if(StringUtils.isNotBlank(page)) {
this.setPage(Integer.valueOf(page));
}
}
public void setRows(String rows) {
if(StringUtils.isNotBlank(rows)) {
this.setRows(Integer.valueOf(rows));
}
}
public void setPagination(String pagination) {
// 只有前台jsp填写了pagination=false,才代表不分页
if(StringUtils.isNotBlank(pagination)) {
this.setPagination(!“false”.equals(pagination));
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Map<String, String[]> getParaMap() {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
各位读者,由于本篇幅度过长,为了避免影响阅读体验,下面我就大概概括了整理了
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-xF6wRbnC-1712769109844)]
[外链图片转存中…(img-1ZsIktxo-1712769109844)]
[外链图片转存中…(img-qby8tjtB-1712769109844)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-FfkXBo4G-1712769109845)]
最后
各位读者,由于本篇幅度过长,为了避免影响阅读体验,下面我就大概概括了整理了
[外链图片转存中…(img-iuQzCeLO-1712769109845)]
[外链图片转存中…(img-VBnZHguu-1712769109845)]
[外链图片转存中…(img-opA5QFTk-1712769109846)]
[外链图片转存中…(img-lzegyMrd-1712769109846)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-gpciXBor-1712769109846)]