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

相关推荐
hhcgchpspk几秒前
flask服务端页面预防被爬措施
后端·python·flask·网络爬虫·防爬
小小张说故事4 分钟前
Python 里 copy.copy() 和 deepcopy() 到底差在哪:拆开 __copy__、__deepcopy__ 和那个防止无限递归的 memo 字典
python
vipxieliang6 分钟前
Python collections:高效容器与实战案例
后端·python
驭渊的小故事19 分钟前
Spring AOP 核心概念与通知类型详解
java·后端·spring
vipxieliang20 分钟前
ValidX vs 手写验证代码:开发效率对比实测
java·spring boot·后端
青少儿编程课堂21 分钟前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
特创数字科技29 分钟前
写了个 Windows 下载器:一键拉 GitHub / Gitee 源码,带 SHA256 校验
python·github
白杨尚青37 分钟前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树
vipxieliang40 分钟前
虚拟线程与 GraalVM:Spring Boot 3.x 云原生性能跃迁
java·spring boot·后端
Rain的Java大神之路41 分钟前
面试官最烦的答案:“我用 Redis + Token”!接口幂等 8 种方案 + 四层防御,把重复扣款工单干到 0
java·后端·面试