1、数据库
复制代码
CREATE TABLE `mp_order` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`order_no` varchar(50) NOT NULL COMMENT '订单编号',
`user_id` bigint NOT NULL COMMENT '关联用户ID',
`amount` decimal(10,2) NOT NULL COMMENT '订单金额',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='订单表';
CREATE TABLE `mp_user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`age` int DEFAULT NULL COMMENT '年龄',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
INSERT INTO `mp_order` (`id`, `order_no`, `user_id`, `amount`, `create_time`) VALUES (1, 'ORDER_001', 1, 100.00, '2025-12-24 09:44:08');
INSERT INTO `mp_order` (`id`, `order_no`, `user_id`, `amount`, `create_time`) VALUES (2, 'ORDER_002', 1, 200.00, '2025-12-24 09:44:08');
INSERT INTO `mp_order` (`id`, `order_no`, `user_id`, `amount`, `create_time`) VALUES (3, 'ORDER_003', 2, 150.00, '2025-12-24 09:44:08');
INSERT INTO `mp_user` (`id`, `username`, `age`, `create_time`) VALUES (1, '张三', 20, '2025-12-24 09:44:08');
INSERT INTO `mp_user` (`id`, `username`, `age`, `create_time`) VALUES (2, '李四', 25, '2025-12-24 09:44:08');
INSERT INTO `mp_user` (`id`, `username`, `age`, `create_time`) VALUES (3, '王五', 30, '2025-12-24 09:44:08');
2、pom.xml文件
复制代码
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-mp-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mp-demo</name>
<description>Spring Boot + MyBatis Plus 分页多表查询样例</description>
<properties>
<java.version>1.8</java.version>
<mybatis-plus.version>3.5.14</mybatis-plus.version>
<mybatis-plus-join.version>1.5.5</mybatis-plus-join.version>
<hutool.version>5.8.23</hutool.version>
</properties>
<dependencies>
<!-- Spring Boot Web核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MySQL驱动(适配8.0) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
<!-- jdk 8+ 引入可选模块 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
<version>3.5.14</version>
</dependency>
<!-- 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>
<!-- Hutool 工具库 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- Lombok(简化实体类) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
3、mybatis plus分页配置
复制代码
package com.example.demo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBatis Plus 配置类(核心:分页插件)
*/
@Configuration
public class MyBatisPlusConfig {
/**
* 分页插件(必须配置,否则分页查询无效)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 适配MySQL的分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
4、业务代码
复制代码
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 订单实体(对应order表)
*/
@Data
@TableName("mp_order") // 指定数据库表名
public class Order {
/**
* 主键ID
*/
private Long id;
/**
* 订单编号
*/
private String orderNo;
/**
* 关联用户ID
*/
private Long userId;
/**
* 订单金额
*/
private BigDecimal amount;
/**
* 创建时间
*/
private LocalDateTime createTime;
}
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 用户实体(对应user表)
*/
@Data
@TableName("mp_user") // 指定数据库表名
public class User {
/**
* 主键ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 年龄
*/
private Integer age;
/**
* 创建时间
*/
private LocalDateTime createTime;
}
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.Order;
import com.github.yulichang.base.MPJBaseMapper;
/**
* 订单Mapper(基础MyBatis Plus Mapper)
*/
public interface OrderMapper extends MPJBaseMapper<Order> {
}
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.User;
import com.example.demo.vo.UserOrderVO;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Param;
/**
* 用户Mapper(继承MPJBaseMapper支持多表连接)
*/
public interface UserMapper extends MPJBaseMapper<User> {
/**
* 单表分页查询用户(基础用法)
*/
IPage<User> selectUserPage(Page<User> page, @Param("age") Integer age);
/**
* 多表连接分页查询(用户+订单)
*/
IPage<UserOrderVO> selectUserOrderPage(Page<UserOrderVO> page, @Param("username") String username);
}
package com.example.demo.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.User;
import com.example.demo.vo.UserOrderVO;
/**
* 用户Service接口
*/
public interface UserService extends IService<User> {
/**
* 单表分页查询用户
* @param pageNum 页码
* @param pageSize 页大小
* @param age 年龄(可选条件)
* @return 分页结果
*/
IPage<User> getUserPage(Integer pageNum, Integer pageSize, Integer age);
/**
* 多表连接分页查询(用户+订单)
* @param pageNum 页码
* @param pageSize 页大小
* @param username 用户名(可选条件)
* @return 分页结果
*/
IPage<UserOrderVO> getUserOrderPage(Integer pageNum, Integer pageSize, String username);
}
package com.example.demo.service.impl;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.Order;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import com.example.demo.vo.UserOrderVO;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 用户Service实现类
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
/**
* 单表分页查询用户
*/
@Override
public IPage<User> getUserPage(Integer pageNum, Integer pageSize, Integer age) {
// 1. 构建分页对象
Page<User> page = new Page<>(pageNum, pageSize);
// 2. 构建查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
if (age != null) {
queryWrapper.ge(User::getAge, age); // 年龄大于等于指定值
}
// 3. 分页查询(MyBatis Plus内置分页方法)
return userMapper.selectPage(page, queryWrapper);
}
/**
* 多表连接分页查询(用户+订单)
* 使用MyBatis Plus Join实现多表连接
*/
@Override
public IPage<UserOrderVO> getUserOrderPage(Integer pageNum, Integer pageSize, String username) {
// 1. 构建分页对象
Page<UserOrderVO> page = new Page<>(pageNum, pageSize);
// 2. 构建多表连接查询条件(MPJ核心用法)
MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
// 主表:user
.selectAll(User.class) // 查询user表所有字段
.leftJoin(Order.class, Order::getUserId, User::getId)
// 自定义查询字段(指定别名,匹配VO的字段)
.selectAs(User::getId, UserOrderVO::getUserId)
.selectAs(Order::getId, UserOrderVO::getOrderId)
.select(Order::getOrderNo)
.select(Order::getAmount)
.selectAs(Order::getCreateTime, UserOrderVO::getOrderCreateTime)
// 条件:用户名模糊查询(Hutool工具类判空)
.like(StrUtil.isNotBlank(username), User::getUsername, username);
// 3. 多表分页查询
return userMapper.selectJoinPage(page, UserOrderVO.class, wrapper);
}
}
package com.example.demo.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import com.example.demo.vo.UserOrderVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户接口控制器
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
/**
* 单表分页查询用户接口
* @param pageNum 页码(默认1)
* @param pageSize 页大小(默认10)
* @param age 年龄(可选)
* @return 分页结果
*/
@GetMapping("/user/page")
public IPage<User> getUserPage(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) Integer age) {
return userService.getUserPage(pageNum, pageSize, age);
}
/**
* 多表连接分页查询接口(用户+订单)
* @param pageNum 页码(默认1)
* @param pageSize 页大小(默认10)
* @param username 用户名(可选)
* @return 分页结果
*/
@GetMapping("/user/joinPage")
public IPage<UserOrderVO> getUserOrderPage(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(required = false) String username) {
return userService.getUserOrderPage(pageNum, pageSize, username);
}
}
5、接口测试
复制代码
2. 接口测试(使用 Postman / 浏览器)
(1)单表分页查询用户
请求地址:http://localhost:8080/user/page?pageNum=1&pageSize=2&age=20
(2)多表连接分页查询
请求地址:http://localhost:8080/user/joinPage?pageNum=1&pageSize=2&username=张三