JDBC实现模糊、动态与分页查询的详解

news2025/5/18 8:14:41

文章目录

  • 一. 模糊查询
    • 1. Mysql的写法
    • 2. JDBC的实现
  • 二. 动态条件查询
    • 1. 创建生成动态条件查询sql的方法
    • 2. 完整的动态条件查询类以及测试类
  • 三. 分页查询
    • 1. 什么是分页查询?
    • 2. 分页查询的分类
    • 3. MySQL的实现
    • 4. JDBC实现
      • 4.1. 创建page页
      • 4.2. 分页的实现

本章来讲一下,JDBC的模糊查询、动态查询以及分页查询的三种查询方式
旨在帮助大家更好的理解和掌握这三种查询方式,希望能够帮助到大家

一. 模糊查询

1. Mysql的写法

这里先回忆一下sql中模糊查询的写法

  1. like: 模糊查询关键字
  2. %: 模糊查询通配符
  3. _: 模糊查询占位符

例如查询学生姓名首字母为A的同学
select * from students where studentName like ‘A%’;

2. JDBC的实现

那么接下来就使用JDBC来实现模糊查询

  1. 获取数据库连接
conn = JdbcUtils.getConnection();
  1. 创建PreparedStatement对象
ps = conn.prepareStatement("select * from users where username like ?");
  1. 参数绑定
ps.setString(1,username);
  1. 执行sql语句并且保存到集合中
rs = ps.executeQuery();
while(rs.next()){
     Users user = new Users();
     user.setUserid(rs.getInt("userid"));
     user.setUsername(rs.getString("username"));
     user.setUserage(rs.getInt("userage"));
     list.add(user);
  }
  1. 释放资源
JdbcUtils.closeResource(rs, ps, connection);

完整代码

public class FuzzyQueryTest {
  /**
   * 根据用户名称模糊查找用户信息
   */
  public List<Users> fuzzyQuery(String username){
    // 用于保存查询的数据
    List<Users> list= new ArrayList<>();
    Connection conn =null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try{ 
      // 获取数据库连接
      conn = JdbcUtils.getConnection();
      // 创建PreparedStatement对象
      ps = conn.prepareStatement("select * from users where username like ?");
      // 参数绑定
      ps.setString(1,username);
      // 执行sql语句
      rs = ps.executeQuery();
      while(rs.next()){
        Users user = new Users();
        user.setUserid(rs.getInt("userid"));
        user.setUsername(rs.getString("username"));
        user.setUserage(rs.getInt("userage"));
        list.add(user);
       }
     }catch(Exception e){
      e.printStackTrace();
     }finally{
      JdbcUtils.closeResource(rs,ps,conn);
     }
    // 返回数据集合 
    return list;
   }

  // 测试代码
  public static void main(String[] args) {
    FuzzyQueryTest ft = new FuzzyQueryTest();
    // 相当于查询
    // select * from users where username like %Y%
    // 并且保存数据集合
    List<Users> users = ft.fuzzyQuery("%Y%");
    for(Users user1 : users){
      System.out.println(user1.getUserid()+" "+user1.getUsername()+" "+user1.getUserage());
     }
   }
}

这里的测试代码实现的是,在users表中查询名字有Y这个字母的所有数据
原表数据为:
在这里插入图片描述
运行后得到结果为
在这里插入图片描述

二. 动态条件查询

动态条件查询就是根据用户给定的条件,来执行对应的查询
例如:要对用户的姓名和年龄对应的数据
这就提升了灵活性,弹性

先复习一下SQL,也就是先使用SQL语句来写一下查询方法
问题:在users表中,查询名字为LuoYi,年龄为18岁的用户信息
那么SQL语句应该是
select * from users where username = ‘LuoYi’ and userage = 18
这样就可以实现查询对应条件的数据了
接下来使用JDBC来实现

1. 创建生成动态条件查询sql的方法

这是在动态条件查询类中创建的一个方法

private String generateSql(Users users){
    // 初始化SQL语句,使用1=1确保后续条件可以直接用and连接 	  
    StringBuffer sb = new StringBuffer("select * from users where 1=1 ");
    // 如果有userid要修改的值
    // 那么就将这个userid添加到这个查询条件中  
    if(users.getUserid() > 0){
      sb.append(" and userid = ").append(users.getUserid());
     }
    // 这个也是,如果username有要修改的值
    // 那么就对应的添加修改条件  
    if(users.getUsername() !=null &&users.getUsername().length() > 0){
      // 因为这里的username是字符串,所以要添加单引号  
      sb.append(" and username = '").append(users.getUsername()).append("'");
     }
    // 同理  
    if(users.getUserage() > 0){
      sb.append(" and userage = ").append(users.getUserage());
     }
    // 最后再将其转换成字符串  
    return sb.toString();
   }

2. 完整的动态条件查询类以及测试类

public class DynamicConditionQueryTest {
  /**
   * 动态条件查询Users
   */
  public List<Users> queryUsers(Users users){
    List<Users> list= new ArrayList<>();


    Connection conn =null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    try{
      //获取数据库连接
      conn = JdbcUtils.getConnection();
      //拼接查询SQL语句
      String sql = this.generateSql(users);
      System.out.println(sql);
      //创建PreparedStatement对象
      ps = conn.prepareStatement(sql);


      //执行sql语句
      rs = ps.executeQuery();
      while(rs.next()){
        Users user = new Users();
        user.setUserid(rs.getInt("userid"));
        user.setUsername(rs.getString("username"));
        user.setUserage(rs.getInt("userage"));
        list.add(user);
       }
     }catch(Exception e){
      e.printStackTrace();
     }finally{
      JdbcUtils.closeResource(rs,ps,conn);
     }
    return list;
   }


  /**
   * 生成动态条件查询sql
   */
  private String generateSql(Users users){
    // 初始化SQL语句,使用1=1确保后续条件可以直接用and连接 	  
    StringBuffer sb = new StringBuffer("select * from users where 1=1 ");
    // 如果有userid要修改的值
    // 那么就将这个userid添加到这个查询条件中  
    if(users.getUserid() > 0){
      sb.append(" and userid = ").append(users.getUserid());
     }
    // 这个也是,如果username有要修改的值
    // 那么就对应的添加修改条件  
    if(users.getUsername() !=null &&users.getUsername().length() > 0){
      // 因为这里的username是字符串,所以要添加单引号  
      sb.append(" and username = '").append(users.getUsername()).append("'");
     }
    // 同理  
    if(users.getUserage() > 0){
      sb.append(" and userage = ").append(users.getUserage());
     }
    // 最后再将其转换成字符串  
    return sb.toString();
   }

// 测试类
public static void main(String[] args) {
    DynamicConditionQueryTest dt = new DynamicConditionQueryTest();
    Users users = new Users();
    // 存放的值就是要修改的条件
    users.setUsername("LuoYi");
    users.setUserage(18);
    List<Users> list = dt.queryUsers(users);
    for(Users user1 : list){
      System.out.println(user1.getUserid()+" "+user1.getUsername()+" "+user1.getUserage());
     }
   }
}

三. 分页查询

1. 什么是分页查询?

当要显示的数据过多时,就会导致内存溢出
那么分页查询就是来避免内存溢出的,降低内存消耗
也就是,我想要一页显示多少,就显示多少

2. 分页查询的分类

  1. 物理分页:
    a. 在数据库执行查询时(实现分页查询),查询需要的数据—依赖数据库的SQL语句
    b. 在SQL查询时,从数据库只检索分页需要的数据
    c. 通常不同的数据库有着不同的物理分页语句
    d. MySql物理分页采用limit关键字
  2. 逻辑分页:
    在sql查询时,先从数据库检索出所有数据的结果集,在程序内,通过逻辑语句获得分页需要的数据
    简单来说,逻辑分页,就是在java程序中,通过循环语句来实现一页显示多少数据

3. MySQL的实现

先复习一下MySQL中的分页查询使用SQL如何实现

select * from tableName limit m,n

其中
m 代表从哪开始(以0为起始)
n 代表需要获取多少行的数据项

例如我们想从users表中先获取前两条数据SQL为:
select * from users limit 0, 2;
那么如果要获取下一页显示2页数据,怎么来实现呢
select * from users limit 2, 2
以此类推,就能够看出规律,n是不变的,然后就看m
m 的公式为: (当前页 - 1) × 每页大小

4. JDBC实现

4.1. 创建page页

这个是分页的实体类

public class Page<T> {
  // 当前页
  private int currentPage;
  // 每页显示的条数
  private int pageSize;
  // 总条数
  private int totalCount;
  // 总页数
  private int totalPage;
  // 结果集
  private List<T> result;
  public int getCurrentPage() {
    return currentPage;
   }
  public void setCurrentPage(int currentPage) {
    this.currentPage = currentPage;
   }
  public int getPageSize() {
    return pageSize;
   }
  public void setPageSize(int pageSize) {
    this.pageSize = pageSize;
   }
  public int getTotalCount() {
    return totalCount;
   }
  public void setTotalCount(int totalCount) {
    this.totalCount = totalCount;
   }
  public int getTotalPage() {
    return totalPage;
   }
  public void setTotalPage(int totalPage) {
    this.totalPage = totalPage;
   }
  public List<T> getResult() {
    return result;
   }
  public void setResult(List<T> result) {
    this.result = result;
   }
}

4.2. 分页的实现

public class PageTest {
  /**
   * 分页查询Users
   */
  public Page<Users> selectPage(Page page){
    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    List<Users> list = new ArrayList<>();
    try{
      // 获取连接对象
      conn = JdbcUtils.getConnection();
      // 创建PrepareStatement对象
      ps = conn.prepareStatement("select * from users limit ?,?");
      // 绑定m参数  m的值 = ( 当前页 - 1 ) * 每页显示的条数
      ps.setInt(1,(page.getCurrentPage()-1)*page.getPageSize());
      // 绑定n参数 n的值为每页显示的条数
      ps.setInt(2,page.getPageSize());
      // 执行查询
      rs = ps.executeQuery();
      // 处理结果集
      while(rs.next()){
        // 完成ORM映射
        Users users = new Users();
        users.setUserid(rs.getInt("userid"));
        users.setUsername(rs.getString("username"));
        users.setUserage(rs.getInt("userage"));
        list.add(users);
       }
      // 将结果集存放到Page对象中。
      page.setResult(list);


      // 查询总条数
      ps = conn.prepareStatement("select count(*) from users");
      // 执行查询
      rs = ps.executeQuery();
      while(rs.next()){
        // 总条数
       int count = rs.getInt(1);
        // 保存总条数
        page.setTotalCount(count);
        // 换算总页数 = 总条数 / 每页显示的条数 向上取整
        int totalPage = (int)Math.ceil(1.0*count/page.getPageSize());
        // 保存总页数
        page.setTotalPage(totalPage);
       }
     }catch(Exception e){
      e.printStackTrace();
     }finally{
      JdbcUtils.closeResource(rs,ps,conn);
     }
    return page;
   }

  // 测试类
  public static void main(String[] args) {
    PageTest pt = new PageTest();
    Page page = new Page();
    page.setCurrentPage(2);
    page.setPageSize(2);
    Page page1 = pt.selectPage(page);
    System.out.println("总条数:"+page1.getTotalCount());
    System.out.println("总页数:"+page1.getTotalPage());
    System.out.println("当前页:"+page1.getCurrentPage());
    System.out.println("每页显示的条数:"+page1.getPageSize());
    List<Users> list = page1.getResult();
    for(Users user:list){
      System.out.println(user.getUserid()+ " "+user.getUsername()+" "+user.getUserage());
     }
   }
}

原数据为
在这里插入图片描述
输出结果
在这里插入图片描述
现在讲完了,三种查询方式,希望能够帮助到大家
感谢~😊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378364.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

域环境信息收集技术详解:从基础命令到实战应用

引言 在企业网络环境中&#xff0c;Active Directory (AD)域服务是微软提供的集中式目录服务&#xff0c;用于管理网络中的用户、计算机和其他资源。对于信息安全专业人员来说&#xff0c;熟练掌握域环境信息收集技术至关重要&#xff0c;无论是进行渗透测试、安全评估还是日常…

【C++ Qt】布局管理器

每日激励&#xff1a;“不设限和自我肯定的心态&#xff1a;I can do all things。 — Stephen Curry” &#x1f914;绪论​&#xff1a; 在Qt开发中&#xff0c;界面布局的合理设计是提升用户体验的关键。早期&#xff0c;开发者常采用绝对定位的方式摆放控件&#xff0c;即通…

vscode用python开发maya联动调试设置

如何在VScode里编写Maya Python脚本_哔哩哔哩_bilibili1 包括1&#xff0c;maya的python全面在vscode支持&#xff0c;2&#xff0c;通过mayacode发送到maya&#xff0c;3同步调试 import maya.cmds as cmds 1、让 maya.cmds编译通过 下载Autodesk_Maya_2018_6_Update_DEVK…

SLAM定位常用地图对比示例

序号 地图类型 概述 1 格栅地图 将现实环境栅格化,每一个栅格用 0 和 1 分别表示空闲和占据状态,初始化为未知状态 0.5 2 特征地图 以点、线、面等几何特征来描绘周围环境,将采集的信息进行筛选和提取得到关键几何特征 3 拓扑地图 将重要部分抽象为地图,使用简单的图形表示…

python的漫画网站管理系统

目录 技术栈介绍具体实现截图![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0ed2084038144499a162b3fb731a5f37.png)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/a76a091066f74a80bf7ac1be489ae8a8.png)系统设计研究方法&#xff1a;设计步骤设计流程核…

源码安装gperftools工具

源码安装gperftools工具 下载gperftools源码 https://github.com/gperftools/gperftools/releases/download/gperftools-2.16/gperftools-2.16.tar.gz 注&#xff1a;需要下载github上release版本&#xff0c;如果直接下载master分支上源码&#xff0c;将可能出现各种编译报错…

前端脚手架开发指南:提高开发效率的核心操作

前端脚手架通过自动化的方式可以提高开发效率并减少重复工作&#xff0c;而最强大的脚手架并不是现成的那些工具而是属于你自己团队量身定制的脚手架&#xff01;本篇文章将带你了解脚手架开发的基本技巧&#xff0c;帮助你掌握如何构建适合自己需求的工具&#xff0c;并带着你…

搜索引擎工作原理|倒排索引|query改写|CTR点击率预估|爬虫

写在前面 使用搜索引擎是我们经常做的事情&#xff0c;搜索引擎的实现原理。 什么是搜索引擎 搜索引擎是一种在线搜索工具&#xff0c;当用户在搜索框输入关键词时&#xff0c;搜索引擎就会将与该关键词相关的内容展示给用户。比较大型的搜索引擎有谷歌&#xff0c;百度&…

Python实例题:Python自动工资条

目录 Python实例题 题目 python-automatic-payroll-slipPython 自动生成工资条脚本 代码解释 加载文件&#xff1a; 获取表头&#xff1a; 写入表头&#xff1a; 生成工资条&#xff1a; 保存文件&#xff1a; 运行思路 注意事项 Python实例题 题目 Python自动工资…

Function Calling万字实战指南:打造高智能数据分析Agent平台

个人主页&#xff1a;Guiat 归属专栏&#xff1a;科学技术变革创新 文章目录 1. Function Calling&#xff1a;智能交互的新范式1.1 Function Calling 技术概述1.2 核心优势分析 2. 数据分析Agent平台架构设计2.1 系统架构概览2.2 核心组件解析2.2.1 函数注册中心2.2.2 Agent控…

线对板连接器的兼容性问题:为何老旧设计难以满足现代需求?

线对板连接器作为电子设备的核心纽带&#xff0c;正面临前所未有的兼容性挑战。某智能工厂升级生产线时发现&#xff0c;沿用十年的2.54毫米间距连接器&#xff0c;在接入新型工业相机时出现30%的信号丢包率&#xff0c;而切换至0.4毫米超密间距连接器后&#xff0c;数据传输速…

AI517 AI本地部署 docker微调(失败)

本地部署AI 计划使用OLLAMA进行本地部署 修改DNS 访问github 刷新缓存 配置环境变量 OLLAMA安装成功 部署成功 计划使用docker进行微调 下载安装docker 虚拟化已开启 开启上面这些 准备下载ubuntu docker ragflow dify 用git去泡

VR和眼动控制集群机器人的方法

西安建筑科技大学信息与控制工程学院雷小康老师团队联合西北工业大学航海学院彭星光老师团队&#xff0c;基于虚拟现实&#xff08;VR&#xff09;和眼动追踪技术实现了人-集群机器人高效、灵活的交互控制。相关研究论文“基于虚拟现实和眼动的人-集群机器人交互方法” 发表于信…

TiDB 中新 Hash Join 的设计与性能优化

原文来源&#xff1a; https://tidb.net/blog/11667c37 本文作者&#xff1a;徐飞 导读 在数据库管理系统&#xff08;DBMS&#xff09;中&#xff0c;连接操作&#xff08;Join&#xff09;是查询处理的核心环节之一&#xff0c;其性能直接影响到整个系统的响应速度和效率…

1.共享内存(python共享内存实际案例,传输opencv frame)

主进程程序 send.py import cv2 import numpy as np from multiprocessing import shared_memory, resource_trackercap cv2.VideoCapture(0) if not cap.isOpened():print("无法打开 RTSP 流&#xff0c;请检查地址、网络连接或 GStreamer 配置。") else:# 创建共…

网页常见水印实现方式

文章目录 1 明水印技术实现1.1 DOM覆盖方案1.2 Canvas动态渲染1.3 CSS伪元素方案2 暗水印技术解析2.1 空域LSB算法2.2 频域傅里叶变换3 防篡改机制设计3.1 MutationObserver防护3.2 Canvas指纹追踪4 前后端实现对比5 攻防博弈深度分析5.1 常见破解手段5.2 进阶防御策略6 选型近…

【ARM】MDK如何将变量存储到指定内存地址

1、 文档目标 在嵌入式系统开发中&#xff0c;通过MDK&#xff08;Microcontroller Development Kit&#xff09;进行工程配置&#xff0c;将指定的变量存储到指定的内存地址上是一项非常重要的技术。这项操作不仅能够满足特定硬件架构的需求&#xff0c;还能优化系统的性能和…

Unity3D仿星露谷物语开发44之收集农作物

1、目标 在土地中挖掘后&#xff0c;洒下种子后逐渐成长&#xff0c;然后使用篮子收集成熟后的农作物&#xff0c;工具栏中也会相应地增加该农作物。 2、修改CropStandard的参数 Assets -> Prefabs -> Crop下的CropStandard&#xff0c;修改其Box Collider 2D的Size(Y…

langchain—chatchat

署部 下载项目 git clone --recursive https://github.com/chatchat-space/Langchain-Chatchat.git 进入目录 cd Langchain-Chatchat anaconda环境准备 创建python环境 conda create -n langchain_env python3.10 -y 激活环境 conda activate langchain_env 验证pyhton环境…

【LeetCode 热题 100】二叉树的最大深度 / 翻转二叉树 / 二叉树的直径 / 验证二叉搜索树

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;LeetCode 热题 100 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 二叉树的中序遍历二叉树的最大深度翻转二叉树对称二叉树二叉树的直径二叉树的层序遍历将有序数组转换为二叉搜索树验…