MyBatisPlus_02_条件构造器与高级功能

【MyBatis-Plus】条件构造器与高级功能:Wrapper、分页、逻辑删除

🔑 关键词:Java、MyBatis-Plus、LambdaQueryWrapper、分页插件、逻辑删除、乐观锁、自动填充


一、条件构造器 Wrapper

1.1 Wrapper 体系

类 用途
QueryWrapper 条件查询,用字符串表示列名
LambdaQueryWrapper 条件查询,用 Lambda 表示列名(推荐)
UpdateWrapper 条件更新,用字符串表示列名
LambdaUpdateWrapper 条件更新,用 Lambda 表示列名(推荐)

💡 推荐 Lambda 风格:编译期检查,避免列名写错。


1.2 LambdaQueryWrapper 常用方法

java 复制代码
// 等价 SQL: SELECT * FROM animal WHERE name = '大熊猫' AND age > 3
List<Animal> list = animalMapper.selectList(
    new LambdaQueryWrapper<Animal>()
        .eq(Animal::getName, "大熊猫")
        .gt(Animal::getAge, 3)
);

常用条件方法:

方法 SQL 示例
eq = .eq(Animal::getAge, 5)
ne != .ne(Animal::getStatus, 0)
gt > .gt(Animal::getAge, 3)
ge >= .ge(Animal::getAge, 3)
lt < .lt(Animal::getAge, 10)
le <= .le(Animal::getAge, 10)
like LIKE '%值%' .like(Animal::getName, "熊")
likeLeft LIKE '%值' .likeLeft(Animal::getName, "熊")
likeRight LIKE '值%' .likeRight(Animal::getName, "熊")
between BETWEEN a AND b .between(Animal::getAge, 1, 10)
in IN (a, b) .in(Animal::getId, List.of(1,2,3))
orderByDesc ORDER BY col DESC .orderByDesc(Animal::getAge)
orderByAsc ORDER BY col ASC .orderByAsc(Animal::getName)
last 拼接任意 SQL .last("LIMIT 10")

1.3 组合条件(OR / AND)

java 复制代码
// 等价: WHERE name LIKE '%熊%' AND (age > 3 OR age < 1)
List<Animal> list = animalMapper.selectList(
    new LambdaQueryWrapper<Animal>()
        .like(Animal::getName, "熊")
        .and(w -> w.gt(Animal::getAge, 3).or().lt(Animal::getAge, 1))
);

1.4 LambdaUpdateWrapper

java 复制代码
// 等价: UPDATE animal SET age = 6 WHERE name = '大熊猫'
animalMapper.update(null,
    new LambdaUpdateWrapper<Animal>()
        .set(Animal::getAge, 6)
        .eq(Animal::getName, "大熊猫")
);

// setSql 自定义
animalMapper.update(null,
    new LambdaUpdateWrapper<Animal>()
        .setSql("age = age + 1")
        .eq(Animal::getId, 1L)
);

二、分页插件

2.1 配置分页插件

java 复制代码
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

2.2 使用分页

java 复制代码
// 查询第1页,每页10条
Page<Animal> page = new Page<>(1, 10);
Page<Animal> result = animalMapper.selectPage(page,
    new LambdaQueryWrapper<Animal>()
        .gt(Animal::getAge, 3)
        .orderByDesc(Animal::getCreateTime)
);

// 获取分页结果
result.getTotal()    // 总记录数
result.getPages()    // 总页数
result.getRecords()  // 当前页数据
result.hasNext()     // 是否有下一页

三、逻辑删除

3.1 什么是逻辑删除?

不真正删除数据,而是标记一个字段表示"已删除"。查询时自动过滤已删除的记录。

3.2 配置

yaml 复制代码
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted      # 逻辑删除字段
      logic-delete-value: 1            # 已删除值
      logic-not-delete-value: 0        # 未删除值

3.3 实体类

java 复制代码
@TableName("animal")
public class Animal {
    private Long id;
    private String name;

    @TableLogic  // 标记为逻辑删除字段
    private Integer deleted;
}

3.4 效果

java 复制代码
// 执行删除 → UPDATE animal SET deleted=1 WHERE id=1 AND deleted=0
animalMapper.deleteById(1L);

// 查询 → SELECT * FROM animal WHERE deleted=0(自动过滤)
animalMapper.selectList(null);

// 真正删除 → 不加 @TableLogic,使用 mapper.delete() 即可

四、乐观锁

4.1 什么是乐观锁?

通过版本号防止并发更新冲突。每次更新时检查版本号,如果被别人改过则更新失败。

4.2 配置

java 复制代码
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

4.3 实体类

java 复制代码
@TableName("animal")
public class Animal {
    private Long id;
    private String name;

    @Version  // 版本号字段
    private Integer version;
}

4.4 效果

java 复制代码
// 查询
Animal animal = animalMapper.selectById(1L);  // version = 1

// 更新 → UPDATE animal SET name='xxx', version=2 WHERE id=1 AND version=1
animal.setName("金丝猴");
int rows = animalMapper.updateById(animal);  // 成功返回1

// 如果此时另一个线程已经更新过,version 变成 2
// 当前线程再更新:WHERE id=1 AND version=1 → 匹配不到,返回0(更新失败)

五、自动填充

5.1 场景

createTime、updateTime 等字段不需要手动设置,自动填充。

5.2 实体类标记

java 复制代码
@TableField(fill = FieldFill.INSERT)
private Date createTime;

@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

5.3 实现 MetaObjectHandler

java 复制代码
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date::new, Date.class);
        this.strictInsertFill(metaObject, "updateTime", Date::new, Date.class);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date::new, Date.class);
    }
}

六、IService 通用 Service

6.1 定义

java 复制代码
// 接口继承 IService
public interface AnimalService extends IService<Animal> { }

// 实现类继承 ServiceImpl
@Service
public class AnimalServiceImpl extends ServiceImpl<AnimalMapper, Animal>
    implements AnimalService { }

6.2 IService 常用方法

方法 说明
save(entity) 插入一条
saveBatch(list) 批量插入
removeById(id) 根据 ID 删除
removeBatchByIds(ids) 批量删除
updateById(entity) 根据 ID 修改
updateBatchById(list) 批量修改
getById(id) 根据 ID 查询
list() 查询全部
page(current, size) 分页查询
count() 查询总数
saveOrUpdate(entity) 有则更新,无则插入
java 复制代码
// saveBatch 批量插入(IService 提供,默认每批 1000 条)
public void importData(List<Animal> list) {
    this.saveBatch(list, 500);  // 每批500条
}

七、面试高频问题

Q1:LambdaQueryWrapper 和 QueryWrapper 的区别?

答 :QueryWrapper 用字符串表示列名(如 .eq("name", "xxx")),列名写错编译时不会报错;LambdaQueryWrapper 用 Lambda 表达式引用实体属性(如 .eq(Animal::getName, "xxx")),编译期检查,类型安全,推荐使用。

Q2:MyBatis-Plus 的逻辑删除怎么用?

答 :实体类字段加 @TableLogic 注解,配置 logic-delete-value 和 logic-not-delete-value。执行 delete 时自动转为 UPDATE SET deleted=1,查询时自动加 WHERE deleted=0。

Q3:MyBatis-Plus 的乐观锁怎么实现?

答 :实体类字段加 @Version 注解,配置 OptimisticLockerInnerInterceptor。更新时 SQL 自动拼接 WHERE version=旧版本号,并将 version+1。如果版本号不匹配则更新失败(返回0),需要业务层重试。


八、总结

功能 核心类/注解 要点
条件构造 LambdaQueryWrapper eq/gt/like/between/orderBy
更新构造 LambdaUpdateWrapper set/setSql
分页 PaginationInnerInterceptor Page 对象 + selectPage
逻辑删除 @TableLogic delete 转 update,查询自动过滤
乐观锁 @Version + 拦截器 版本号比对防并发冲突
自动填充 MetaObjectHandler createTime/updateTime 自动设置
通用 Service IService / ServiceImpl saveBatch/updateBatchById 等

💡 学习建议:条件构造器是 MyBatis-Plus 最核心的功能,多写多练,配合动物园管理系统的查询需求实际运用。

相关推荐
geovindu1 小时前
rust: search
开发语言·后端·rust
垚垚学技术_聚焦云原生1 小时前
Ansible Role 生产环境标准目录结构与规范化实践
java·elasticsearch·ansible
霸道流氓气质1 小时前
Spring AI Alibaba Graph Studio 入门指南:可视化Agent编排与调试平台
java·人工智能·spring
SimonKing1 小时前
Stream-Nexus:我的轻量级推送中间件(sse、websocket)终于定下来了
java·后端·程序员
重生之小比特1 小时前
【C++进阶】封装红⿊树实现mymap和myset
开发语言·c++
打工仔折腾 AI1 小时前
网易UU远程实测:手机控电脑做Python开发和Agent调试的真实体验
人工智能·后端·python·智能手机·性能优化·电脑·ai agent 实战
边境悍匪1 小时前
蜗牛学苑 Java 智能体学习 Day49|贯穿项目 5 订单下单业务 思维导图复盘
java·开发语言·spring boot·学习·阿里云
轩轶子1 小时前
Python CLI Todo:一次数据结构错误引发的 Bug
数据结构·python·bug
鬼手点金2 小时前
Claude Code示范案例-修复 Bug 工作流
java·服务器·前端·javascript·bug·openclaw