java每日精进 5.20【MyBatis 联表分页查询】

1. MyBatis XML 实现分页查询

1.1 实现方式

MyBatis XML 是一种传统的 MyBatis 使用方式,通过在 XML 文件中编写 SQL 语句,并结合 Mapper 接口和 Service 层实现分页查询。分页需要手动编写两条 SQL 语句:一条查询分页数据列表,另一条查询总记录数。分页参数(如页码和每页大小)通过 LIMIT 语句手动实现。

1.2 代码解析

以下是文档中提供的 MyBatis XML 分页查询代码的解析:

1.2.1 xml代码

// 获取所有用户(分页,支持用户名模糊查询)@GetMapping("/xmluserpage")public IPage<User> getUsersByPage(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size,@RequestParam(required = false) String username) {return userService.getUserPage(page, size, username);}
@Overridepublic IPage<User> getUserPage(int page, int size, String username) {Page<User> userPage = new Page<>(page, size);return userMapper.selectPageCustom(userPage, username);}
// 自定义分页查询(单表)IPage<User> selectPageCustom(Page<User> page, @Param("username") String username);
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.home.mapper.UserMapper"><!-- 自定义分页查询 --><select id="selectPageCustom" resultType="com.home.pojo.User">SELECT id, username, password, email, create_time, update_timeFROM user<where><if test="username != null and username != ''">AND username LIKE CONCAT('%', #{username}, '%')</if></where></select></mapper>

2. MyBatis XML 联表查询

2.1背景代码

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>CRUDSystem</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging> <!-- 建议改为jar,Spring Boot默认打包为可执行jar --><name>CRUDSystem</name><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><spring-boot.version>2.7.18</spring-boot.version><mybatis-plus.version>3.5.3.1</mybatis-plus.version><mybatis-plus-join.version>1.4.10</mybatis-plus-join.version></properties><dependencies><!-- MyBatis Plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency><!-- MyBatis Plus Join --><dependency><groupId>com.github.yulichang</groupId><artifactId>mybatis-plus-join-boot-starter</artifactId><version>${mybatis-plus-join.version}</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-extension</artifactId><version>${mybatis-plus.version}</version></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!-- Spring Boot 核心 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>${spring-boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring-boot.version}</version></dependency><!-- Lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency><!-- 测试依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${spring-boot.version}</version><scope>test</scope></dependency></dependencies><build><finalName>CRUDSystem</finalName><plugins><!-- Spring Boot 打包插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin><!-- 编译插件 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target><release>17</release></configuration></plugin></plugins></build>
</project>
@Data
@TableName("user")
public class User {@TableId(type = IdType.AUTO)private Long id;private String username;private String password;private String email;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}
@Data
@TableName("`order`")
public class Order {@TableId(type = IdType.AUTO)private Long id;private Long userId;private Long productId;private Integer quantity;private BigDecimal totalPrice;private Integer status;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}
//字段平铺
@Data
public class UserOrderDetailDO extends User {private Long orderId;private BigDecimal totalPrice;private Integer orderStatus;
}
//字段内嵌
@Data
public class UserOrderDetail2DO extends User {private Order order;
}

2.2字段平铺

// 字段平铺:获取用户订单详情(分页,订单状态和用户名过滤)@GetMapping("/orders")public IPage<UserOrderDetailDO> getUserOrders(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size,@RequestParam Integer status,@RequestParam(required = false) String username) {return userService.getUserOrderPage(page, size, status, username);}@Overridepublic IPage<UserOrderDetailDO> getUserOrderPage(int page, int size, Integer status, String username) {Page<UserOrderDetailDO> userOrderPage = new Page<>(page, size);return userMapper.selectListByStatusAndUsername(userOrderPage, status, username);}
// 字段平铺:联表查询用户和订单(状态为已支付,用户名模糊匹配)default IPage<UserOrderDetailDO> selectListByStatusAndUsername(Page<UserOrderDetailDO> page,@Param("status") Integer status,@Param("username") String username) {return selectJoinPage(page, UserOrderDetailDO.class, new MPJLambdaWrapper<User>() // 改为 selectJoinPage.selectAll(User.class).selectAs(Order::getId, UserOrderDetailDO::getOrderId).selectAs(Order::getTotalPrice, UserOrderDetailDO::getTotalPrice).selectAs(Order::getStatus, UserOrderDetailDO::getOrderStatus).eq(Order::getStatus, status).leftJoin(Order.class, Order::getUserId, User::getId).like(username != null, User::getUsername, username));}

等价于以下SQL

SELECT 
    u.*,
    o.id AS orderId,
    o.total_price AS totalPrice,
    o.status AS orderStatus
FROM 
    user u
LEFT JOIN 
    `order` o ON u.id = o.user_id  -- 注意这里应该是 user_id 而不是 o.id
WHERE 
    o.status = 1 
    AND u.username LIKE '%username%'

查询结果:

{"records": [{"id": 1,"username": "user1","password": "password123","email": "user1@example.com","createTime": "2025-05-20T10:15:33","updateTime": "2025-05-20T10:15:33","orderId": 1,"totalPrice": 999.99,"orderStatus": 1}],"total": 2,"size": 1,"current": 1,"orders": [],"optimizeCountSql": true,"searchCount": true,"maxLimit": null,"countId": null,"pages": 2
}

2.3字段嵌入

// 字段内嵌:获取用户订单详情(分页,订单状态和用户名过滤)@GetMapping("/orders2")public IPage<UserOrderDetail2DO> getUserOrders2(@RequestParam(defaultValue = "1") int page,@RequestParam(defaultValue = "10") int size,@RequestParam Integer status,@RequestParam(required = false) String username) {return userService.getUserOrderPage2(page, size, status, username);}
@Overridepublic IPage<UserOrderDetail2DO> getUserOrderPage2(int page, int size, Integer status, String username) {Page<UserOrderDetail2DO> userOrderPage = new Page<>(page, size);return userMapper.selectList2ByStatusAndUsername(userOrderPage, status, username);}
// 字段内嵌:联表查询用户和订单(状态为已支付,用户名模糊匹配)default IPage<UserOrderDetail2DO> selectList2ByStatusAndUsername(Page<UserOrderDetail2DO> page,@Param("status") Integer status,@Param("username") String username) {return selectJoinPage(page, UserOrderDetail2DO.class, new MPJLambdaWrapper<User>() // 改为 selectJoinPage.selectAll(User.class).selectAssociation(Order.class, UserOrderDetail2DO::getOrder).eq(Order::getStatus, status).leftJoin(Order.class, Order::getUserId, User::getId).like(username != null, User::getUsername, username));}

等价SQL:

SELECT 
    u.*, 
    o.*
FROM 
    t_user u
LEFT JOIN 
    t_order o ON o.user_id = u.id
WHERE 
    o.status = #{status}
    AND (#{username} IS NULL OR u.username LIKE CONCAT('%', #{username}, '%'))
LIMIT #{page.size} OFFSET #{page.offset}

返回值为:

{"records": [{"id": 1,"username": "user1","password": "password123","email": "user1@example.com","createTime": "2025-05-20T10:15:33","updateTime": "2025-05-20T10:15:33","order": {"id": 1,"userId": 1,"productId": 1,"quantity": 1,"totalPrice": 999.99,"status": 1,"createTime": "2025-05-20T10:16:00","updateTime": "2025-05-20T10:16:00"}}],"total": 2,"size": 1,"current": 1,"orders": [],"optimizeCountSql": true,"searchCount": true,"maxLimit": null,"countId": null,"pages": 2
}

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

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

相关文章

linux taskset 查询或设置进程绑定CPU

1、安装 taskset larkubuntu&#xff1a;~$ sudo apt-get install util-linux larkubuntu&#xff1a;~$ taskset --help 用法&#xff1a; taskset [选项] [mask | cpu-list] [pid|cmd [args...]] 显示或更改进程的 CPU 关联性。 选项&#xff1a; -a&#xff0c; --all-tasks…

Python应用字符串格式化初解

大家好!在 Python 编程中&#xff0c;字符串格式化是一项基础且实用的技能。它能让你更灵活地拼接字符串与变量&#xff0c;使输出信息更符合需求。本文将为和我一样的初学者详细介绍 Python 字符串格式化的常用方法。 定义: 字符串格式化就是将变量或数据插入到字符串中的特定…

EasyRTC嵌入式音视频通信SDK一对一音视频通信,打造远程办公/医疗/教育等场景解决方案

一、方案概述​ 数字技术发展促使在线教育、远程医疗等行业对一对一实时音视频通信需求激增。传统方式存在低延迟、高画质及多场景适配不足等问题&#xff0c;而EasyRTC凭借音视频处理、高效信令交互与智能网络适配技术&#xff0c;打造稳定低延迟通信&#xff0c;满足基础通信…

SEO长尾词优化精准布局

内容概要 长尾关键词作为SEO策略的核心要素&#xff0c;其价值在于精准捕捉细分需求与低竞争流量入口。相较于短尾词的高泛化性&#xff0c;长尾词通过语义扩展与场景化组合&#xff0c;能够更高效地匹配用户搜索意图&#xff0c;降低优化成本的同时提升转化潜力。本文将从词库…

【MySQL】第7节|Mysql锁机制与优化实践以及MVCC底层原理剖析

锁等待分析 我们通过检查InnoDB_row_lock相关的状态变量来分析系统上的行锁的争夺情况 示例场景 假设有两个用户同时操作账户表 accounts&#xff08;主键为 id&#xff09;&#xff1a; 1. 用户A&#xff1a;执行转账&#xff0c;锁定账户 id1 并等待3秒&#xff1a; BEG…

基于规则引擎与机器学习的智能Web应用防火墙设计与实现

基于规则引擎与机器学习的智能Web应用防火墙设计与实现 引言&#xff1a;智能防御的必然选择 在2023年OWASP最新报告中&#xff0c;传统Web应用防火墙&#xff08;WAF&#xff09;对新型API攻击的漏报率高达67%&#xff0c;而误报导致的正常业务拦截损失每年超过2.3亿美元。面…

GIM发布新版本了 (附rust CLI制作brew bottle流程)

GIM 发布新版本了&#xff01;现在1.3.0版本可用了 可以通过brew upgrade git-intelligence-message升级。 初次安装需要先执行 brew tap davelet/gim GIM 是一个根据git仓库内文件变更自动生成git提交消息的命令行工具&#xff0c;参考前文《GIM: 根据代码变更自动生成git提交…

PyQt5高效布局指南:QTabWidget与QStackedWidget实战解析

&#x1f50d; 问题背景 当界面控件过多时&#xff0c;直接平铺会导致窗口拥挤、用户体验下降。PyQt5提供了两种高效容器控件&#xff1a; QTabWidget&#xff1a;选项卡式布局&#xff0c;支持直接切换不同功能模块QStackedWidget&#xff1a;堆栈式布局&#xff0c;需配合导…

《2.2.1顺序表的定义|精讲篇》

上一节学习了线性表的逻辑结构&#xff0c;线性表需要实现哪些基本运算/操作&#xff1f;在本节中&#xff0c;我们将学习顺序表的定义、顺序表的特性&#xff0c;以及如何用代码来实现顺序表。下个小节我们会介绍基于顺序存储&#xff08;这种存储结构&#xff09;如何用代码具…

【 大模型技术驱动智能网联汽车革命:关键技术解析与未来趋势】

大模型技术驱动智能网联汽车革命&#xff1a;关键技术解析与未来趋势 关键词总结&#xff1a; 大模型技术&#xff1a;LLM、VLM、MLLM、Transformer架构核心场景&#xff1a;智能驾驶、智能座舱、智能网联关键技术&#xff1a;端到端系统、BEVOCC网络、多模态融合、强化学习挑…

Rocketmq broker 是主从架构还是集群架构,可以故障自动转移吗

RocketMQ Broker的架构与故障转移机制 RocketMQ的Broker架构同时采用了主从架构和集群架构&#xff0c;并且支持故障自动转移。下面详细说明&#xff1a; 一、架构类型 1. 集群架构 RocketMQ天然支持分布式集群部署 一个RocketMQ集群包含多个Broker组(每组有主从) 不同Bro…

从零开始建立个人品牌并验证定位变现性的方法论——基于开源AI大模型、AI智能名片与S2B2C商城生态的实证研究

摘要&#xff1a;本文提出一种融合开源AI大模型、AI智能名片与S2B2C商城小程序源码的"最小测试闭环"方法论&#xff0c;通过技术赋能实现个人品牌定位的精准验证与变现路径优化。以某美妆领域自由职业者为例&#xff0c;其通过开源AI大模型完成能力图谱构建与资源匹配…

SQL进阶之旅 Day 2:高效的表设计与规范:从基础到实战

【SQL进阶之旅 Day 2】高效的表设计与规范&#xff1a;从基础到实战 开篇 在数据库开发中&#xff0c;一个良好的表设计不仅能够提高查询效率&#xff0c;还能避免冗余数据和一致性问题。本文作为"SQL进阶之旅"系列的第2天&#xff0c;将重点介绍高效的表设计与规范…

Java—— IO流的应用

带权重的点名系统 案例要求 文件中有学生的信息&#xff0c;每个学生的信息独占一行。包括学生的姓名&#xff0c;性别&#xff0c;权重 要求每次被抽中的学生&#xff0c;再次被抽中的概率在原先的基础上降低一半。 本题的核心就是带权重的随机 分析 权重&#xff0c;权重和…

Docker中部署Alertmanager

在 Docker 中部署 Alertmanager&#xff08;通常与 Prometheus 告警系统配合使用&#xff09;的步骤如下&#xff1a; 一、拉取镜像prom/alertmanager docker pull prom/alertmanager二、 创建 Alertmanager 配置文件 首先准备Alertmanager的配置文件 alertmanager.yml(如存…

【大模型面试每日一题】Day 27:自注意力机制中Q/K/V矩阵的作用与缩放因子原理

【大模型面试每日一题】Day 27&#xff1a;自注意力机制中Q/K/V矩阵的作用与缩放因子原理 &#x1f4cc; 题目重现 &#x1f31f;&#x1f31f; 面试官&#xff1a;请解释Transformer自注意力机制中Query、Key、Value矩阵的核心作用&#xff0c;并分析为何在计算注意力分数时…

AI+能碳管理系统:全生命周期碳管理

在"双碳"目标的时代背景下&#xff0c;AI赋能的能碳管理系统正在重新定义企业碳管理的边界与深度。这套系统犹如一位不知疲倦的碳管家&#xff0c;从原材料采购到产品报废&#xff0c;在每一个价值环节编织起精密的碳管理网络&#xff0c;实现从微观设备到宏观战略的…

k8s1.27版本集群部署minio分布式

需求&#xff1a; 1.创建4个pv&#xff0c;一个pv一个minio-pod。使用sts动态分配pvc(根据存储类找到pv)。----持久化 2.暴露minio的9001端口。&#xff08;nodeport&#xff09;----管理界面 镜像&#xff1a;minio/minio:RELEASE.2023-03-20T20-16-18Z--->换国内源 说明…

使用 OpenCV 实现 ArUco 码识别与坐标轴绘制

&#x1f3af; 使用 OpenCV 实现 ArUco 码识别与坐标轴绘制&#xff08;含Python源码&#xff09; Aruco 是一种广泛用于机器人、增强现实&#xff08;AR&#xff09;和相机标定的方形标记系统。本文将带你一步一步使用 Python OpenCV 实现图像中多个 ArUco 码的检测与坐标轴…

Qt 控件发展历程 + 目标(1)

文章目录 声明简述控件的发展历程学习目标QWidget属性 简介&#xff1a;这篇文章只是一个引子&#xff0c;介绍一点与控件相关的但不重要的内容&#xff08;浏览浏览即可&#xff09;&#xff0c;这一章节最为重要的还是要把之后常用且重要的控件属性和作用给学透&#xff0c;学…