提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、条件构造器

MyBatis-Plus 提供强大的 Wrapper 类体系,支持通过链式调用构建复杂查询条件,覆盖日常开发中各类 SQL 场景需求。

1、核心 Wrapper 类型

类型 适用场景 特点
QueryWrapper 构建 SELECT/UPDATE/DELETE 条件 字段名硬编码
LambdaQueryWrapper 构建 SELECT/UPDATE Lambda 表达式,避免硬编码
UpdateWrapper 特殊 SET 语句构建 支持复杂 SET 逻辑
LambdaUpdateWrapper 特殊 SET 语句构建 Lambda 表达式优化

Wrapper构造复杂SQL
在这里插入图片描述

基础查询示例

在这里插入图片描述
查询用户名包含 “o” 且余额 ≥1000 的用户,返回指定字段。

SQL 查询

SELECT id, username, info, balance 
FROM user 
WHERE username LIKE '%o%' AND balance >= 1000;

使用 QueryWrapper 实现查询

@Test
void testQueryWrapper() {
    // 1. 构建条件构造器(字段硬编码方式)
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.select("id", "username", "info", "balance") // 指定返回字段
          .like("username", "o")                      // 模糊查询:username LIKE '%o%'
          .ge("balance", 1000);                       // 范围查询:balance >= 1000

    // 2. 执行查询
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

更新操作示例

场景一:基础更新

将用户名为 “jack” 的用户余额设为 2000。

SQL 查询
UPDATE user 
SET balance = 2000 
WHERE username = 'jack';
使用 QueryWrapper 实现更新
@Test
void testUpdateByQueryWrapper() {
    // 1. 准备更新实体(SET 字段)
    User updateEntity = new User();
    updateEntity.setBalance(2000);

    // 2. 构建条件构造器
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("username", "jack"); // 精确匹配条件

    // 3. 执行更新
    userMapper.update(updateEntity, wrapper);
}

场景二:复杂更新

对 ID 为 1、2、4 的用户执行余额扣减 200 操作。

SQL 查询
UPDATE user 
SET balance = balance - 200 
WHERE id IN (1, 2, 4);
使用 UpdateWrapper 实现更新
@Test
void testUpdateWrapper() {
    // 1. 定义操作参数
    List<Long> targetIds = Arrays.asList(1L, 2L, 4L);
    int deductionAmount = 200;

    // 2. 构建 UpdateWrapper(支持复杂 SET 语句)
    UpdateWrapper<User> wrapper = new UpdateWrapper<>();
    wrapper.setSql("balance = balance - 200" ) 
          .in("id", id);  

    // 3. 执行更新(传入 null 表示不通过实体类设置字段)
    userMapper.update(null, wrapper);
}

条件构造器的用法:

  1. QueryWrapperLambdaQueryWrapper通常用来构建selectdeleteupdatewhere条件部分
  2. UpdateWrapperLambdaUpdateWrapper通常只有在set语句比较特殊才使用
  3. 尽量使用LambdaQueryWrapperLambdaUpdateWrapper,避免硬编码

2、Lambda 表达式优化

通过 Lambda 表达式消除字段硬编码,提升代码可维护性。

改造查询示例

@Test
void testLambdaQueryWrapper() {
    // 1. 构建 Lambda 条件构造器
    LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
    lambdaWrapper.select(User::getId, User::getUsername, 
                        User::getInfo, User::getBalance)  // 指定查询的字段
                .like(User::getUsername, "o")   // username LIKE '%o%'
                .ge(User::getBalance, 1000);    // balance >= 1000

    // 2. 执行查询
    List<User> users = userMapper.selectList(lambdaWrapper);
    users.forEach(System.out::println);
}

二、自定义 SQL 整合

结合条件构造器与自定义 SQL 片段处理复杂业务场景。

可以利用MyBatisPlusWrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分

场景说明

对指定 ID 的用户进行余额扣减操作,同时通过 Wrapper 动态构建条件。
在这里插入图片描述

Mapper 接口定义

public interface UserMapper extends BaseMapper<User> {
    // 使用 @Param(Constants.WRAPPER) 注解绑定 Wrapper
    void updateBalanceByIds(@Param(Constants.WRAPPER) QueryWrapper<User> wrapper, 
                           @Param("amount") int amount);
}

XML 映射文件

<update id="updateBalanceByIds">
    UPDATE user
    SET balance = balance - #{amount}
    WHERE id IN
    <foreach collection="ids" separator="," item="id" open="(" close=")">
        #{id}
    </foreach>
</update>

在这里插入图片描述

业务层调用

@Test
void testCustomSqlUpdate() {
    // 1. 定义要更新的 ID 列表
    List<Long> ids = List.of(1L, 2L, 4L);
    // 2. 定义减少的金额
    int amount = 200;
    // 3. 构建条件
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
        .in(User::getId, ids); // 条件:id IN (1, 2, 4)
    // 4. 自定义 SQL 方法调用
    userMapper.updateBalanceByIds(wrapper, amount);
}

三、Service 接口

1. 基础接口定义继承 IService

通过继承 IService<T> 接口获得 MyBatis-Plus 内置的通用 CRUD 方法

public interface IUserService extends IService<User> {

    /**
     * 根据用户名查询用户详细信息(自定义扩展方法)
     * @param username 用户名
     * @return 用户完整信息(包含关联实体)
     */
    UserVO getUserDetailByUsername(String username);

    /**
     * 批量更新用户状态(自定义业务方法)
     * @param ids 用户ID集合
     * @param status 新状态值
     * @return 是否更新成功
     */
    boolean updateUserStatus(List<Long> ids, Integer status);
}

2. 服务实现类规范

继承 ServiceImpl<M, T> 并实现自定义接口,通过组合方式实现功能

@Service
public class UserServiceImpl 
       extends ServiceImpl<UserMapper, User>  // 继承MP提供的基类
       implements IUserService {              // 实现自定义接口

    @Autowired
    private AccountService accountService;    // 可注入其他服务

    // ================= 实现自定义方法 =================
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO getUserDetailByUsername(String username) {
        // 1. 查询基础信息
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        User user = this.getOne(wrapper);

        // 2. 获取关联账户信息
        Account account = accountService.getByUserId(user.getId());

        // 3. 组装VO
        return UserVO.builder()
                .user(user)
                .account(account)
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserStatus(List<Long> ids, Integer status) {
        // 批量更新操作
        return this.update(new LambdaUpdateWrapper<User>()
                .set(User::getStatus, status)
                .in(User::getId, ids));
    }

    // ================= 可覆盖基类方法 =================
    @Override
    public boolean save(User entity) {
        // 自定义保存逻辑(如密码加密)
        entity.setPassword(encrypt(entity.getPassword()));
        return super.save(entity);
    }
}

3. 结构优势说明

组件 功能说明
IService<T> 提供 20+ 通用 CRUD 方法(saveBatch、page、lambdaQuery 等)
ServiceImpl<M,T> 实现 IService 的默认方法,提供 baseMapper 快速访问 DAO 层
自定义接口 扩展业务相关方法,保持接口语义清晰
事务控制 通过 @Transactional 注解保证业务操作原子性

4. 方法调用示例

// 自动注入服务
@Autowired
private IUserService userService;

// 使用通用方法
User user = userService.getById(1L);
Page<User> page = userService.page(new Page<>(1, 10), queryWrapper);

// 调用自定义方法
UserVO userVO = userService.getUserDetailByUsername("mike");
boolean result = userService.updateUserStatus(Arrays.asList(1L,2L), 2);

MP的Service接口使用流程是怎样的?

1. 自定义 Service 接口继承 IService 接口

首先,你需要创建一个自定义的 Service 接口,并继承 MP 提供的通用 IService 接口。

public interface IUserService extends IService<User> {
    // 可以在这里定义额外的业务方法
}
  • IService<T> 是 MyBatis-Plus 提供的通用服务接口,包含了许多常用的 CRUD 方法。
  • 如果有额外的业务需求,可以在 IUserService 中定义自己的方法。

2. 实现自定义 Service 接口并继承Servicelmpl类

创建一个实现类来实现自定义的 Service 接口,并继承 MP 提供的 ServiceImpl 类。

@Service // 使用 Spring 的注解将该类注册为 Bean
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    // 实现自定义的业务方法
}
  • ServiceImpl<M, T> 是 MyBatis-Plus 提供的通用服务实现类:
    • M 是 Mapper 接口的类型(例如 UserMapper)。
    • T 是实体类的类型(例如 User)。
  • @Service 注解是 Spring 的注解,用于将该实现类注册为 Spring 容器中的 Bean,方便后续注入和使用。

3. Mapper 接口的定义

确保你已经定义了对应的 Mapper 接口,并继承 MP 提供的 BaseMapper

public interface UserMapper extends BaseMapper<User> {
    // 可以在这里定义额外的查询方法
}
  • BaseMapper<T> 是 MyBatis-Plus 提供的通用 Mapper 接口,包含了基本的 CRUD 方法。
  • 如果有额外的查询需求,可以在 UserMapper 中定义自己的方法。

4. 配置 Mapper 扫描

确保在 Spring Boot 的启动类或配置类上添加了 @MapperScan 注解,用于扫描 Mapper 接口。

@SpringBootApplication
@MapperScan("com.example.mapper") // 替换为你的 Mapper 接口所在的包路径
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

5. 在 Controller 组件中使用 Service

最后在需要使用的地方(如 Controller)通过依赖注入的方式使用自定义的 Service。

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private IUserService userService;

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getById(id); // 调用 MP 提供的通用方法
    }

    @PostMapping
    public boolean addUser(@RequestBody User user) {
        return userService.save(user); // 调用 MP 提供的通用方法
    }
}

总结:完整流程

  1. 定义自定义 Service 接口,继承 IService
  2. 创建自定义 Service 实现类,继承 ServiceImpl 并实现自定义接口。
  3. 定义对应的 Mapper 接口,继承 BaseMapper
  4. 配置 @MapperScan 注解,确保 Mapper 被正确扫描。
  5. 在需要的地方(如 Controller)注入并使用自定义 Service

通过这种方式可以充分利用 MyBatis-Plus 提供的通用方法,同时也可以根据业务需求扩展自己的功能。


基于Restful风格实现下面的接口:
在这里插入图片描述

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data // 自动生成 getter/setter、toString 等方法
@ApiModel(description = "用户V0实体") // Swagger 注解,描述实体类
public class UserV0 {

    @ApiModelProperty("用户id") // Swagger 注解,描述字段
    private Long id;

    @ApiModelProperty("用户名")
    private String username;

    @ApiModelProperty("详细信息")
    private String info; // 原来的 "string" 应为 "String"

    @ApiModelProperty("使用状态(1正常 2冻结)")
    private Integer status;

    @ApiModelProperty("账户余额")
    private Integer balance;
}

四、QueryWrapper 查询方法与 UpdateWrapper 更新方法对照手册

QueryWrapper

核心方法

方法 描述 SQL 示例
eq 等于 = WHERE username = 'Tom'
ne 不等于 <> WHERE age <> 18
gt 大于 > WHERE price > 100
between 范围查询 WHERE date BETWEEN ? AND ?
like 模糊匹配 WHERE name LIKE '%T%'
orderByAsc 升序排序 ORDER BY price ASC
orderByDesc 降序排序 ORDER BY weight DESC

其他常用方法

方法 描述 示例
or OR 条件拼接 .eq("A",1).or().eq("B",2)
in IN 查询 .in("status", 1, 2, 3)
apply 自定义 SQL 片段 .apply("date_format(date,'%Y-%m') = '2023-01'")

示例

@Test  
public void testQueryWrapperExample() {  
    // 构建查询条件
    QueryWrapper<User> qw = new QueryWrapper<User>();  
    qw.eq("username", "Tom")  
      .like("email", "qq.com")  
      .gt("age", 30);  

    // 查询符合条件的用户列表
    List<User> userList = userMapper.selectList(qw);  
    for (User user : userList) {  
        logger.info("User: {}", user);  
    }  

    // 多条件更新(示例)
    User updateUser = new User();
    updateUser.setName("newName");
    updateUser.setEmail("newEmail");
    int updateResult = userMapper.update(updateUser, qw);  
    logger.info("Update affected rows: {}", updateResult);

    // 多条件删除(示例)
    int deleteResult = userMapper.delete(qw);  
    logger.info("Delete affected rows: {}", deleteResult);
}

代码功能说明

  • QueryWrapper<User>:用于构建查询条件。
  • eq("username", "Tom"):表示查询 username 等于 "Tom" 的记录。
  • like("email", "qq.com"):表示查询 email 字段中包含 "qq.com" 的记录。
  • gt("age", 30):表示查询 age 大于 30 的记录。
  • userMapper.selectList(qw):执行查询并返回符合条件的用户列表。
  • 多条件更新和删除:注释掉的代码展示了如何根据条件进行更新或删除操作。

UpdateWrapper

核心方法

方法 描述 SQL 示例
set 设置更新字段 SET name = 'Tom'
setSql 直接写更新表达式 SET price = price + 10
lambda Lambda 条件构造 .eq(User::getId, 1)

示例

@Test
public void testUpdateWrapper() {
//创建一个UpdateWrapper对象,用于构建更新操作的查询条件。
UpdateWrapper uw = new UpdateWrapper();
//字段是"name",值是"Tom"。
uw.set("name", "Tom");

//使用set方法设置另一个字段"age"的值为35。
uw.set("age", 35);

//使用gt方法设置一个大于条件,即"salary"字段的值必须大于3000。
uw.gt("salary", 3000);

//使用lt方法设置一个小于条件,即"salary"字段的值必须小于10000。
uw.lt("salary", 10000);

//使用like方法设置一个模糊匹配条件,即"name"字段的值必须以"T"开头。
uw.like("name", "T%");

int result = employeeMapper.update(null, uw);
System.out.println(result);
}
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐