MybatisPlus难懂点

MyBatis-Plus 中「静态 LambdaQuery(Db.lambdaQuery)」和「普通 LambdaQuery」的区别、使用场景,以及自定义 SQL 和条件构造器的选择逻辑,我会从新手视角一步步讲清楚,避免复杂术语(lambdaupdate)。

首先明确核心结论:两者本质都是构建 Lambda 条件查询,只是调用方式、作用域、灵活性不同,先看代码对比,再讲区别。

1. 两种写法的代码示例

假设你有 Address 实体类,对应 address 表:

java 复制代码
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.Db;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

// 1. 普通 LambdaQuery(基于 Wrapper/Service)
// 方式1:手动 new LambdaQueryWrapper
LambdaQueryWrapper<Address> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Address::getUserId, 1L);
List<Address> addressList1 = addressMapper.selectList(queryWrapper);

// 方式2:基于 Service 层(需要 AddressService 继承 IService<Address>)
List<Address> addressList2 = addressService.lambdaQuery()
                                          .eq(Address::getUserId, 1L)
                                          .list();

// 2. 静态 LambdaQuery(Db 工具类)
List<Address> addressList3 = Db.lambdaQuery(Address.class)
                              .eq(Address::getUserId, 1L)
                              .list();
2. 核心区别 & 使用场景
特性 静态 LambdaQuery(Db.lambdaQuery) 普通 LambdaQuery(Wrapper/Service)
调用方式 静态调用 Db.xxx,无需注入 Mapper/Service 需先注入 xxxMapperxxxService
代码简洁度 极简,一行搞定,无需额外依赖 稍繁琐,需创建 Wrapper 或注入 Service
灵活性 基础查询够用,复杂场景(联表、自定义 SQL)弱 可扩展,支持自定义 Wrapper、联表等
适用场景 快速简单查询(单表、少量条件) 复杂业务查询(多条件、分页、联表)
依赖 仅需引入 MyBatis-Plus 核心包 需定义 Mapper 接口、Service 接口并注入
3. 什么时候用?
  • 用 Db.lambdaQuery :临时 / 简单查询场景(比如工具类、测试代码、单表单条件查询),不想写 Mapper/Service,只想快速查数据。例:"查用户 ID=1 的所有地址",无需注入 AddressService,直接 Db.lambdaQuery(Address.class).eq(Address::getUserId, 1).list()

  • 用普通 LambdaQuery :业务核心逻辑、复杂查询场景(比如多条件组合、分页、排序、联表),或需要和 Service/Mapper 层解耦的场景。例:"查用户 ID=1 且状态为启用、按创建时间排序的分页地址列表",用 Service 层的 lambdaQuery 更易扩展:

    java 复制代码
    // 复杂查询示例(普通 LambdaQuery)
    Page<Address> page = new Page<>(1, 10); // 分页:第1页,每页10条
    addressService.lambdaQuery()
                  .eq(Address::getUserId, 1L)
                  .eq(Address::getStatus, 1) // 状态启用
                  .orderByDesc(Address::getCreateTime)
                  .page(page);

二、自定义 SQL vs 条件构造器(Wrapper)

这是 MyBatis-Plus 新手最容易纠结的点:什么时候用条件构造器,什么时候写自定义 SQL?

1. 核心定位
  • 条件构造器(LambdaQueryWrapper/QueryWrapper) :MyBatis-Plus 封装的 "无 SQL 写法",通过 Java 代码拼接 WHERE 条件,适合单表、常规条件查询(eq/ne/like/gt/lt 等),无需手写 SQL,降低出错率。

  • 自定义 SQL :手写 XML 或注解 SQL,适合复杂场景(联表查询、多表关联、复杂子查询、聚合函数、自定义 JOIN/ON 条件等),条件构造器搞不定的场景都用这个。

2. 代码示例对比
场景 1:条件构造器能搞定的(单表常规查询)
java 复制代码
// 条件构造器:查用户ID=1、地址包含"北京"的记录
List<Address> list = addressService.lambdaQuery()
                                  .eq(Address::getUserId, 1L)
                                  .like(Address::getDetail, "北京")
                                  .list();
// 底层自动生成 SQL:SELECT * FROM address WHERE user_id = ? AND detail LIKE ?
场景 2:必须自定义 SQL 的(联表查询)

需求:查用户 ID=1 的用户信息 + 对应的默认地址(关联 user 表和 address 表)。

java 复制代码
// 1. Mapper 接口定义自定义 SQL(注解方式)
public interface UserMapper extends BaseMapper<User> {
    @Select("SELECT u.*, a.detail AS default_address " +
            "FROM user u " +
            "LEFT JOIN address a ON u.id = a.user_id AND a.is_default = 1 " +
            "WHERE u.id = #{userId}")
    UserVO getUserWithDefaultAddress(@Param("userId") Long userId);
}

// 2. 调用
UserVO userVO = userMapper.getUserWithDefaultAddress(1L);
3. 选择原则(新手直接套)
场景类型 选条件构造器 选自定义 SQL
表关联 单表 多表联查(JOIN/LEFT JOIN)
条件复杂度 常规条件(eq/like/gt/ 排序) 复杂子查询、聚合函数(sum/count/group by)
SQL 灵活性 低(框架封装) 高(完全自定义)
维护成本 低(改 Java 代码即可) 高(需维护 SQL 语法)
4. 进阶:条件构造器 + 自定义 SQL 结合用

如果既想要条件构造器的灵活(动态拼接 WHERE 条件),又需要自定义 SQL(比如联表),MyBatis-Plus 支持混合使用:

java 复制代码
// Mapper 接口(自定义 SQL + 条件构造器)
public interface AddressMapper extends BaseMapper<Address> {
    @Select("SELECT a.*, u.username FROM address a LEFT JOIN user u ON a.user_id = u.id ${ew.customSqlSegment}")
    List<AddressVO> selectAddressWithUser(@Param(Constants.WRAPPER) LambdaQueryWrapper<Address> wrapper);
}

// 调用:用条件构造器拼条件,自定义 SQL 做联表
LambdaQueryWrapper<Address> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Address::getUserId, 1L).like(Address::getDetail, "北京");
List<AddressVO> list = addressMapper.selectAddressWithUser(wrapper);

总结

1. 静态 vs 普通 LambdaQuery
  • Db.lambdaQuery简单场景速查,无需注入 Mapper/Service,代码极简;
  • 普通 LambdaQuery(Wrapper/Service):复杂业务查询,灵活扩展,适配分页、多条件、排序等场景。
2. 条件构造器 vs 自定义 SQL
  • 条件构造器:单表常规查询优先用,不用写 SQL,维护简单;
  • 自定义 SQL:多表联查、复杂子查询、聚合函数 必须用,灵活性最高;
  • 进阶场景可结合两者:自定义 SQL 做联表,条件构造器动态拼 WHERE 条件。

简单记:能不用写 SQL 就用条件构造器,搞不定了就写自定义 SQL;能少写代码就用 Db 静态查询,业务核心逻辑就用 Service 层的 LambdaQuery。

相关推荐
一只专注api接口开发的技术猿2 小时前
微服务架构下集成淘宝商品 API 的实践与思考
java·大数据·开发语言·数据库·微服务·架构
AC赳赳老秦2 小时前
Dify工作流+DeepSeek:运维自动化闭环(数据采集→报告生成)
android·大数据·运维·数据库·人工智能·golang·deepseek
明洞日记2 小时前
【软考每日一练009】计算机系统性能评价:基准程序分类与 TPC 实战案例详解
大数据·数据库
Hoxy.R2 小时前
海量数据库安装部署初体验
服务器·网络·数据库
癫狂的兔子2 小时前
【Python】【爬虫】爬取虎扑网NBA排行数据
数据库·爬虫·python
迷路剑客3 小时前
ES-7.10-高亮HighLight知识点总结
java·数据库·mybatis
程序边界3 小时前
解锁时序数据新玩法:金仓数据库实战体验分享
数据库
汉堡go3 小时前
python_chapter6
前端·数据库·python
范纹杉想快点毕业3 小时前
嵌入式工程师一年制深度进阶学习计划(纯技术深耕版)
linux·运维·服务器·c语言·数据库·算法