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 最核心的功能,多写多练,配合动物园管理系统的查询需求实际运用。

相关推荐
SL_staff39 分钟前
告别报表重复开发:JVS-BI 模板市场的参数化继承实践
java·数据分析·数据可视化
进击的明明40 分钟前
当AI开始“边想边干”:深入聊聊ReAct,以及如何用Python手搓一个简单Agent
python·面试·agent
全栈弄潮儿2 小时前
Python实战第8期:函数
后端·python·编程语言
SL_staff2 小时前
从邮箱传文档到协同流重构:企业文档协作的系统性破局实践
java·开源·github
卷无止境3 小时前
暗流与破局:AI时代的代码安全审查工具全景指南
后端·python
smallyoung3 小时前
告别N+1:Spring Boot 一键数据翻译框架体系
java·后端·架构
Bazingga5 小时前
Java16 record 完整拆解——语法、语义、限制、反射
java·后端
卷无止境6 小时前
一人公司的全栈选型指南:让 AI Agent 写得快,也让生意跑得稳
后端·python
SL_staff7 小时前
规则联动:给工厂装上‘自动化神经反射弧’——JVS·物联网平台规则引擎实战教程
java·人工智能·物联网
骑着蜗牛撵大象3277 小时前
Linux 进程间通信之管道:从 pipe() 的内核语义到 FIFO 落地排错
android·java·linux·系统编程·fifo·管道·进程间通信