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

【MybatisPlus】join关联查询MPJLambdaWrapper

【MybatisPlus】join关联查询MPJLambdaWrapper

  • 【一】前期准备
    • 【1】引入依赖
    • 【2】核心组件说明
  • 【二】基础案例:一对一关联查询
    • 【1】场景
    • 【2】定义实体类
    • 【3】定义 DTO(接收关联结果)
    • 【4】自定义 Mapper 接口
    • 【5】关联查询实现
    • 【6】执行结果说明
  • 【三】进阶案例:一对多关联查询
    • 【1】场景
    • 【2】定义订单实体和 DTO
    • 【3】一对多关联查询实现
  • 【四】分页关联查询
  • 【五】关键使用细节
    • 【1】关联条件语法
    • 【2】字段别名与 DTO 映射
    • 【3】条件查询
    • 【4】只查询部分字段
    • 【5】一对多结果封装

MyBatis-Plus 本身并未直接提供关联查询(Join)的内置 API,但其生态中有一个常用的扩展库 mybatis-plus-join(官方维护的扩展),可以通过 MPJLambdaWrapper 实现类似 MyBatis 的关联查询功能,且语法更简洁。以下是其使用细节及详细案例。

【一】前期准备

【1】引入依赖

在 pom.xml 中添加 mybatis-plus-join 依赖(需与 MyBatis-Plus 版本兼容,推荐 1.4.4+):

<dependency><groupId>com.github.yulichang</groupId><artifactId>mybatis-plus-join-boot-starter</artifactId><version>1.4.4</version>
</dependency>

【2】核心组件说明

(1)MPJLambdaWrapper:关联查询的核心条件构造器,支持 leftJoin、rightJoin、innerJoin 等关联方式。
(2)MPJBaseMapper:需自定义 Mapper 继承该接口,以获得关联查询的方法(如 selectJoinList、selectJoinPage)。
(3)DTO 类:用于接收关联查询的结果(包含多表字段),需与查询的字段映射。

【二】基础案例:一对一关联查询

【1】场景

主表:user(用户表),字段:id、name、age、address_id
关联表:address(地址表),字段:id、province、city、detail
需求:查询用户信息及关联的地址信息(user.address_id = address.id)

【2】定义实体类

// 用户表实体
@Data
@TableName("user")
public class User {private Long id;private String name;private Integer age;private Long addressId; // 关联地址表的id
}// 地址表实体
@Data
@TableName("address")
public class Address {private Long id;private String province;private String city;private String detail;
}

【3】定义 DTO(接收关联结果)

// 包含用户和地址的关联结果
@Data
public class UserAddressDTO {// 用户表字段private Long userId;       // 对应user.id(注意别名,避免与address.id冲突)private String userName;   // 对应user.nameprivate Integer userAge;   // 对应user.age// 地址表字段private Long addressId;    // 对应address.idprivate String province;private String city;private String detail;
}

【4】自定义 Mapper 接口

// 用户Mapper,继承MPJBaseMapper以支持关联查询
public interface UserMapper extends MPJBaseMapper<User> {
}

【5】关联查询实现

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;/*** 查询用户及关联的地址信息*/public List<UserAddressDTO> getUserWithAddress() {// 构建关联查询条件MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()// 主表:user,查询字段(别名映射到DTO).select(User::getId, User::getName, User::getAge).selectAs(User::getId, UserAddressDTO::getUserId)       // user.id -> userId.selectAs(User::getName, UserAddressDTO::getUserName)   // user.name -> userName.selectAs(User::getAge, UserAddressDTO::getUserAge)     // user.age -> userAge// 左关联地址表(address),别名a.leftJoin(Address.class, Address::getId, User::getAddressId, "a")// 关联表字段(别名a的字段映射到DTO).select("a.id AS addressId")       // address.id -> addressId.select("a.province").select("a.city").select("a.detail")// 条件:查询年龄>18的用户.gt(User::getAge, 18);// 执行关联查询,返回DTO列表return userMapper.selectJoinList(UserAddressDTO.class, wrapper);}
}

【6】执行结果说明

生成的 SQL 类似:

SELECT t.id AS userId, t.name AS userName, t.age AS userAge, a.id AS addressId, a.province, a.city, a.detail 
FROM user t 
LEFT JOIN address a ON a.id = t.address_id 
WHERE t.age > 18

【三】进阶案例:一对多关联查询

【1】场景

主表:user(用户表)
关联表:order(订单表),字段:id、user_id、amount、create_time
需求:查询用户信息及关联的所有订单(order.user_id = user.id)

【2】定义订单实体和 DTO

// 订单表实体
@Data
@TableName("order")
public class Order {private Long id;private Long userId; // 关联用户表的idprivate BigDecimal amount;private LocalDateTime createTime;
}// 包含用户和订单列表的DTO
@Data
public class UserOrderDTO {private Long userId;private String userName;private List<Order> orders; // 一对多:用户的多个订单
}

【3】一对多关联查询实现

public List<UserOrderDTO> getUserWithOrders() {MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()// 主表字段.selectAs(User::getId, UserOrderDTO::getUserId).selectAs(User::getName, UserOrderDTO::getUserName)// 左关联订单表(order),别名o.leftJoin(Order.class, Order::getUserId, User::getId, "o")// 关联表字段(全部订单字段).select("o.id", "o.user_id", "o.amount", "o.create_time")// 条件:订单金额>100.gt(Order::getAmount, new BigDecimal("100"));// 执行查询,MyBatis-Plus会自动将同一用户的订单封装到List<Order>中return userMapper.selectJoinList(UserOrderDTO.class, wrapper);
}

【四】分页关联查询

在一对一查询基础上,实现分页查询(每页 10 条)。

public IPage<UserAddressDTO> getUserWithAddressPage(int pageNum, int pageSize) {// 构建分页对象Page<User> page = new Page<>(pageNum, pageSize);// 关联查询条件(同基础案例)MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>().selectAs(User::getId, UserAddressDTO::getUserId).selectAs(User::getName, UserAddressDTO::getUserName).leftJoin(Address.class, Address::getId, User::getAddressId, "a").select("a.province", "a.city").eq(User::getName, "张三"); // 按用户名筛选// 执行分页关联查询return userMapper.selectJoinPage(page, UserAddressDTO.class, wrapper);
}

【五】关键使用细节

【1】关联条件语法

leftJoin(关联表实体类, 关联表关联字段, 主表关联字段, 关联表别名)
例如:leftJoin(Address.class, Address::getId, User::getAddressId, “a”) 等价于 LEFT JOIN address a ON a.id = t.address_id(t 是主表默认别名)。

【2】字段别名与 DTO 映射

当多表字段名冲突(如 id)时,必须用 selectAs 或 select(“别名.字段 AS DTO属性”) 指定别名,否则会导致字段覆盖。
DTO 中的属性名需与查询的别名一致(支持驼峰映射,如 user_id 可映射到 userId)。

【3】条件查询

可通过 eq、gt、like 等方法添加主表或关联表的条件,关联表条件需用别名或 Lambda 指定,例如:
.eq(“a.province”, “广东省”) 或 .eq(Address::getProvince, “广东省”)(需确保关联表已添加)。

【4】只查询部分字段

尽量避免使用 selectAll(实体类)(查询所有字段),而是通过 select 精确指定所需字段,减少数据传输。

【5】一对多结果封装

当关联表为 “多” 的一方时(如一个用户多个订单),DTO 中需定义 List<关联实体> 类型的属性,MyBatis-Plus 会自动按主表 ID 分组封装。

http://www.lryc.cn/news/609274.html

相关文章:

  • Javaweb————Windows11系统和idea2023旗舰版手动配置Tomcat9全流程解析
  • 性能测试工具ApacheBench、Jmeter
  • ospf笔记和 综合实验册
  • 在Ansys Mechanical中对磨损进行建模
  • 重生之我在10天内卷赢C++ - DAY 10
  • 分布式文件系统05-生产级中间件的Java网络通信技术深度优化
  • STM32F103_Bootloader程序开发13 - 巧用逆向拷贝,实现固件更新的“准原子”操作,无惧升级中的意外掉电
  • Ethereum: 了解炙手可热 Layer 2 解决方案 Base
  • Spring AOP_2
  • Python 小数据池(Small Object Pool)详解
  • NX969NX972美光固态闪存NX975NX977
  • 深度学习中的三种Embedding技术详解
  • Maven - 依赖的生命周期详解
  • MySQL深度理解-MySQL锁机制
  • vllm0.8.5:思维链(Chain-of-Thought, CoT)微调模型的输出结果包括</think>,提供一种关闭思考过程的方法
  • Remix框架:高性能React全栈开发实战
  • 音视频学习(四十九):音频有损压缩
  • 数据结构-双链表
  • 网络通信与Socket套接字详解
  • Flink程序关键一步:触发环境执行
  • 13-day10生成式任务
  • 全面解析 BGE Embedding 模型:训练方式、模型系列与实战用法
  • python批量gif图片转jpg
  • C++ vector容器详解:从基础使用到高效实践
  • 【GitHub探索】Agent开发平台CozeStudio开源版本踩坑体验
  • Obsidian结合CI/CD实现自动发布
  • 【设计模式】4.装饰器模式
  • 第二节 YOLOv5参数
  • 电商系统定制开发流程:ZKmall开源商城需求分析到上线全程可控
  • Linux命令基础(上)