当前位置: 首页 > news >正文

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.xdnf.cn/news/541909.html

相关文章:

  • NODE-I916 I721模块化电脑发布,AI算力与超低功耗的完美平衡
  • Java 06API时间类
  • CHI中ordering的抽象
  • 第四章、SKRL(2): API(Models and Model instantiators)
  • 银行反欺诈理论、方法与实践总结(下):解决方案
  • 【动手学深度学习】1.1~1.2 机器学习及其关键组件
  • 珈和科技贺李德仁院士荣膺国际数字地球学会会士:以时空智能赋能可持续发展目标 绘就数字地球未来蓝图
  • 基于pycharm,python,flask,tensorflow,keras,orm,mysql,在线深度学习sql语句检测系统
  • HarmonyOS5云服务技术分享--云缓存快速上手指南
  • 创建型:建造者模式
  • 跨域_Cross-origin resource sharing
  • SpringBoot-6-在IDEA中配置SpringBoot的Web开发测试环境
  • Spring Boot 多参数统一加解密方案详解:从原理到实战
  • 物流项目第三期(统一网关、工厂模式运用)
  • 普通人如何开发并训练自己的脑力?
  • npm vs npx 终极指南:从原理到实战的深度对比 全面解析包管理器与包执行器的核心差异,助你精准选择工具
  • 零基础深入解析 ngx_http_session_log_module
  • 视频太大?用魔影工厂压缩并转MP4,画质不打折!
  • 【缺陷】GaN和AlN中的掺杂特性
  • 小程序涉及提供提供文本深度合成技术,请补充选择:深度合成-AI问答类目
  • Golang的文件上传与下载
  • C++ 读取英伟达显卡名称、架构及算力
  • 服务器数据恢复—Linux系统服务器崩溃且重装系统的数据恢复案例
  • 常见高速电路设计与信号完整性核心概念
  • ubuntu下docker安装mongodb-支持单副本集
  • XTDrone配置ALOAM三维激光SLAM环境
  • GitLab部署
  • std::chrono类的简单使用实例及分析
  • 传输层协议:UDP和TCP
  • [原创](现代Delphi 12指南):[macOS 64bit App开发]: 如何获取目录大小?