JavaWeb+Druid连接池+MySQL实现商品的多条件搜索与分页(超详细的~)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: JavaWeb+Druid连接池+MySQL实现商品的多条件搜索与分页(超详细的~)

引言

Hello, 大家好,我是Bug终结者,一周一更如约而至,同时文章持续更新,每周为大家带来我学习路上的一些经验,与代码分享,同时驱使自己进步,成为更好的自己。
同时,疫情又紧张了起来,小伙伴们都做好防护,戴好口罩,不给病毒留任何 趁虚而入的机会!身体健康第一!

所用技术栈

JavaWeb, Druid连接池, MySQL5.7

项目结构
在这里插入图片描述

为什么需要多条件搜索
答:因为在数据量过大时,展示的数据太多,这对用户造成很不好的操作,想要拿到一条数据,却不知如何下手,难道去数据库里找吗?

于是多条件搜索,多个条件并到一块,来显示符合条件的数据记录,这大大的提高的用户的操作体验,所以说,使用多条件搜索对用户友好,提高的程序的可维护性。

为什么需要分页
答:因为数据量过大展示的数据过多,一打开页面,让一次性展示出来这对服务器来说是个灾难,所以以分页展示来减轻服务器的压力,同时方便了操作,多条件搜索与分页结合可以说是完美搭配,大大提示程序的操作感,提高查询数据的速度。

@TOC

数据表

/*
SQLyog Ultimate v12.09 (64 bit)
MySQL - 5.7.24 
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;

CREATE TABLE `t_goods` (
  `order_id` int(11) NOT NULL AUTO_INCREMENT,
  `goods_name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL,
  `goods_price` decimal(10,3) DEFAULT NULL,
  `goods_addr` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci


insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('1','华为手机','2999.000','中国大陆');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('2','苹果手机','5999.000','美国');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('3','小米手机','1999.000','中国大陆');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('4','三星手机','3999.000','韩国');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('5','苹果','1.000','中国大陆');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('6','香蕉','3.000','菲律宾');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('7','桃','1.000','中国大陆');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('8','DELL电脑','5999.000','美国');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('9','联想电脑','4999.000','中国大陆');
insert into `t_goods` (`order_id`, `goods_name`, `goods_price`, `goods_addr`) values('10','苹果电脑','9999.000','美国');

分页

分页思路:

1.在展示商品页面写上前一页与后一页,这里我用的是组件,bootstarp
2.在servlet页面调用service层page方法,传入参数为当期页,每页的固定记录数,返回分页对象
3.service实现类调用dao层page方法返回list商品集合,调用getCount方法获取当期商品的总记录数,构造PageInfo对象将截取到的商品集合,总记录数,当前页,每页的固定数传入
4.PageInfo类中初始化参数,计算共多少页,修正当前页,如果小于1,固定为1,如果大于当前页,哪就为当前页,计算前一页与后一页,与修正当前页思路相同。

PageInfo类

package com.wanshi.bean;

import java.util.List;

public class PageInfo {

    private List goodsList;
    
    private Integer pageNumb;
    private Integer pageSize;
    private Integer pageCount;
    private Integer rowCount;
    private Integer prevPageNumb;
    private Integer nextPageNumb;
    
    public PageInfo(List<Goods> goodsList, Integer rowCount, Integer pageNumb, Integer pageSize) {
        // TODO Auto-generated constructor stub
        //先将商品集合,商品总记录数,每页的记录数赋值
        this.goodsList = goodsList;
        this.rowCount = rowCount;
        this.pageSize = pageSize;
    
        //计算共有几页
        this.pageCount = this.rowCount / this.pageSize;
        //如果页数不够,那就再补上一页
        if (this.rowCount % this.pageSize != 0) {
            this.pageCount ++;
        }
        //修正当前页
        this.pageNumb = pageNumb;
        if (this.pageNumb < 1) {
            this.pageNumb = 1;
        }
        if (this.pageNumb > this.pageCount) {
            this.pageNumb = this.pageCount;
        }
        
        //前一页
        this.prevPageNumb = this.pageNumb - 1;
        if (this.prevPageNumb < 1) {
            this.prevPageNumb = 1;
        }
        //后一页
        this.nextPageNumb = this.pageNumb + 1;
        if (this.nextPageNumb > this.pageCount) {
            this.nextPageNumb = this.pageCount;
        }
    }

    public List getGoodsList() {
        return goodsList;
    }

    public Integer getPageNumb() {
        return pageNumb;
    }

    public Integer getPageSize() {
        return pageSize;
    }

    public Integer getRowCount() {
        return rowCount;
    }

    public Integer getPrevPageNumb() {
        return prevPageNumb;
    }

    public Integer getNextPageNumb() {
        return nextPageNumb;
    }

    public Integer getPageCount() {
        return pageCount;
    }
    
}

多条件查询

1.获取要查询的条件,作为参数传入page方法,
2.传入dao层后,dao层实现类判断不为null时,搜索查询该条件的记录
具体代码如下

GoodsDaoImpl实现类

package com.wanshi.dao.impl;

import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.commons.lang.math.NumberUtils;

import com.alibaba.druid.util.StringUtils;
import com.wanshi.bean.Goods;
import com.wanshi.dao.GoodsDao;

public class GoodsDaoImpl extends BaseDao implements GoodsDao{

    @Override
    public List<Goods> queryAllGoods() throws Exception {
        // TODO Auto-generated method stub
        QueryRunner qur = initQueryRunner();
        String sql = "select * from t_goods";
        List<Goods> goodsList = qur.query(sql, new BeanListHandler<Goods>(Goods.class));
        return goodsList;
    }

    public String strSql(String goodsName, String strMinPrice, String strMaxPrice, String goodsAddr) {
        String sql = "";
        if (!StringUtils.isEmpty(goodsName)) {
            sql += " and goods_name like '%"+goodsName+"%'";
        }
        if ((!StringUtils.isEmpty(strMinPrice) && NumberUtils.isNumber(strMinPrice))
                && (!StringUtils.isEmpty(strMaxPrice) && NumberUtils.isNumber(strMaxPrice))) {
            sql += "and goods_price between "+Double.valueOf(strMinPrice)+" and "+Double.valueOf(strMaxPrice)+" ";
        }
        if (!StringUtils.isEmpty(goodsAddr)) {
            sql += "and goods_addr like '%"+goodsAddr+"%'";
        }
        return sql;
    }
    
    @Override
    public List<Goods> page(Integer pageNumb, Integer pageSize, String goodsName, String strMinPrice, String strMaxPrice, String goodsAddr) throws Exception {
        // TODO Auto-generated method stub
        QueryRunner qur = initQueryRunner();
        String sql = "select * from t_goods where 1 = 1 ";
        sql += strSql(goodsName, strMinPrice, strMaxPrice, goodsAddr);
        sql += " limit ?, ?";
        return qur.query(sql, new BeanListHandler<Goods>(Goods.class), (pageNumb - 1) * pageSize, pageSize);
    }

    @Override
    public Integer getCount(String goodsName, String strMinPrice, String strMaxPrice, String goodsAddr) throws Exception {
        // TODO Auto-generated method stub
        QueryRunner qur = initQueryRunner();
        String sql = "select count(1) from t_goods where 1 = 1 ";
        sql += strSql(goodsName, strMinPrice, strMaxPrice, goodsAddr);
        Long count = qur.query(sql, new ScalarHandler<Long>());
        System.out.println(sql);
        System.out.println(count);
        return count.intValue();
    }

}

GetGoodsListServlet类

package com.wanshi.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

import com.wanshi.bean.PageInfo;
import com.wanshi.service.GoodsService;
import com.wanshi.service.impl.GoodsServiceImpl;

@WebServlet("/getGoodsList")
public class GetGoodsListServlet extends HttpServlet{

    private static final Integer pageSize = 3;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取查询条件
        String strPageNumb = req.getParameter("pageNumb");
        String goodsName = req.getParameter("goods_name");
        String strMinPrice = req.getParameter("goods_min_price");
        String strMaxPrice = req.getParameter("goods_max_price");
        String goodsAddr = req.getParameter("goods_addr");
        Integer pageNumb = 1;
        if (!StringUtils.isEmpty(strPageNumb)) {
            pageNumb = Integer.valueOf(strPageNumb);
        }
        GoodsService goodsService = new GoodsServiceImpl();
        //转发至列表页
        try {
            PageInfo pager = goodsService.page(pageNumb, pageSize, goodsName, strMinPrice, strMaxPrice, goodsAddr);
            req.setAttribute("goods_name", goodsName);
            req.setAttribute("min_price", strMinPrice);
            req.setAttribute("max_price", strMaxPrice);
            req.setAttribute("goods_addr", goodsAddr);
            req.setAttribute("pager", pager);
            req.getRequestDispatcher("/WEB-INF/list.jsp")
            .forward(req, resp);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

效果展示
在这里插入图片描述
查询商品名称包含苹果的
在这里插入图片描述
查询0-6000的价格并且是苹果的商品
在这里插入图片描述
查询产地为中国的商品
在这里插入图片描述

ok,效果展示到这里,今天的分享到此结束了,如果代码有我未找出的bug,愿各位大神在评论区指出,项目仅为学习中的经验分享,同时提升了能力,从而进入下一步的学习阶段,好了,我们下周见!

若有需要源码的,评论区留言

卑微博主在线求个赞~😁

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
6月前
|
自然语言处理 搜索推荐 关系型数据库
MySQL实现文档全文搜索,分词匹配多段落重排展示,知识库搜索原理分享
本文介绍了在文档管理系统中实现高效全文搜索的方案。为解决原有ES搜索引擎私有化部署复杂、运维成本高的问题,我们转而使用MySQL实现搜索功能。通过对用户输入预处理、数据库模糊匹配、结果分段与关键字标红等步骤,实现了精准且高效的搜索效果。目前方案适用于中小企业,未来将根据需求优化并可能重新引入专业搜索引擎以提升性能。
262 5
|
8月前
|
SQL 缓存 关系型数据库
如何解决MySQL 的深度分页问题?
在构建高性能Web应用程序时,数据库查询性能至关重要。本文深入探讨了MySQL中`LIMIT ... OFFSET ...`语法的性能瓶颈,并介绍了一种更高效的分页方法——游标分页(Cursor Pagination)。通过记录每页最后一个记录的唯一标识,游标分页能显著提升查询效率,将时间复杂度从O(n + m)降低到O(log n + m),特别适用于大规模数据的分页查询场景。此外,文章还介绍了其他优化方法,如覆盖索引分页、分区表、缓存和基于时间戳的分页,并提供了实践中的最佳建议,帮助开发者选择最适合的分页策略,提升系统性能和用户体验。
472 9
|
4月前
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
7月前
|
SQL 关系型数据库 MySQL
MySQL 中的全文索引:强大的文本搜索利器
MySQL 的全文索引是一种用于快速搜索大量文本数据的特殊索引。它通过对文本内容进行分析(如分词、去除停用词等)并构建倒排索引,实现高效查找。创建全文索引使用 `CREATE FULLTEXT INDEX`,搜索时使用 `MATCH AGAINST` 语句。适用于 `CHAR`、`VARCHAR`、`TEXT` 等字段,但需注意性能影响和正确使用搜索语法。
227 22
|
7月前
|
监控 关系型数据库 MySQL
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
689 9
|
存储 关系型数据库 MySQL
mysql数据库查询时用到的分页方法有哪些
【8月更文挑战第16天】在MySQL中,实现分页的主要方法包括:1)使用`LIMIT`子句,简单直接但随页数增加性能下降;2)通过子查询优化`LIMIT`分页,提高大页码时的查询效率;3)利用存储过程封装分页逻辑,便于复用但需额外维护;4)借助MySQL变量实现,可能提供更好的性能但实现较复杂。这些方法各有优缺点,可根据实际需求选择适用方案。
867 2
|
9月前
|
关系型数据库 MySQL PHP
php实现一个简单的MySQL分页
通过本文的详细步骤和代码示例,我们实现了一个简单的PHP MySQL分页功能。主要步骤包括计算总记录数、设置分页参数、查询当前页的数据以及生成分页链接。这种分页方式适用于大多数Web应用,能够有效提升用户体验和页面响应速度。
244 4
|
9月前
|
SQL 关系型数据库 MySQL
mysql分页读取数据重复问题
在服务端开发中,与MySQL数据库进行数据交互时,常因数据量大、网络延迟等因素需分页读取数据。文章介绍了使用`limit`和`offset`参数实现分页的方法,并针对分页过程中可能出现的数据重复问题进行了详细分析,提出了利用时间戳或确保排序规则绝对性等解决方案。
385 1
|
10月前
|
SQL NoSQL 关系型数据库
2024Mysql And Redis基础与进阶操作系列(5)作者——LJS[含MySQL DQL基本查询:select;简单、排序、分组、聚合、分组、分页等详解步骤及常见报错问题所对应的解决方法]
MySQL DQL基本查询:select;简单、排序、分组、聚合、分组、分页、INSERT INTO SELECT / FROM查询结合精例等详解步骤及常见报错问题所对应的解决方法
|
12月前
|
算法 关系型数据库 MySQL
MySQL高级篇——排序、分组、分页优化
排序优化建议、案例验证、范围查询时索引字段选择、filesort调优、双路排序和单路排序、分组优化、带排序的深分页优化
MySQL高级篇——排序、分组、分页优化

推荐镜像

更多