MyBatis-Plus 用了就回不去,这些功能真香

之前项目用的原生 MyBatis,一个简单的分页查询要写 SQL + PageHelper + 一堆 XML。换了 MyBatis-Plus 之后,大部分 CRUD 一行代码搞定。

基础 CRUD

java 复制代码
// Entity
@Data
@TableName("sys_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private String email;
    private Integer status;
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createdAt;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updatedAt;
    @TableLogic
    private Integer deleted;  // 逻辑删除
}

// Mapper --- 只写一个接口,什么都不用定义
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

// Service
@Service
public class UserService extends ServiceImpl<UserMapper, User> {
}

// 使用
// 插入
userService.save(new User().setName("Alice").setEmail("alice@test.com"));

// 根据 ID 查询
User user = userService.getById(1L);

// 更新
userService.updateById(new User().setId(1L).setName("Alice Updated"));

// 删除(逻辑删除,实际是 UPDATE SET deleted=1)
userService.removeById(1L);

条件构造器

java 复制代码
// 复杂查询不用写 SQL
List<User> users = userService.list(
    new LambdaQueryWrapper<User>()
        .eq(User::getStatus, 1)
        .like(User::getName, "alice")
        .between(User::getCreatedAt, startDate, endDate)
        .orderByDesc(User::getCreatedAt)
        .last("LIMIT 10")  // 直接拼 SQL(慎用)
);

// 统计数量
long count = userService.count(
    new LambdaQueryWrapper<User>()
        .eq(User::getStatus, 1)
        .ge(User::getCreatedAt, LocalDate.now().minusDays(7))
);

// 只查部分字段
List<User> partial = userService.list(
    new LambdaQueryWrapper<User>()
        .select(User::getId, User::getName)
        .eq(User::getStatus, 1)
);

LambdaQueryWrapper 用方法引用代替字符串字段名,编译时就能检查字段是否存在,比 QueryWrapper 的字符串安全。

分页

java 复制代码
// 配置分页插件(一次性)
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

// 使用
Page<User> page = userService.page(
    new Page<>(1, 20),  // 第 1 页,每页 20 条
    new LambdaQueryWrapper<User>()
        .eq(User::getStatus, 1)
        .orderByDesc(User::getCreatedAt)
);

// 结果
page.getRecords()   // 当前页数据
page.getTotal()     // 总条数
page.getPages()     // 总页数
page.getCurrent()   // 当前页码

不用 PageHelper,不用写 LIMIT,MP 自动帮你拼。

自动填充

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

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createdAt", LocalDateTime::now, LocalDateTime.class);
        this.strictInsertFill(metaObject, "updatedAt", LocalDateTime::now, LocalDateTime.class);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime::now, LocalDateTime.class);
    }
}

插入和更新的时候自动填充时间字段,不用在每个 Service 里手动 setCreatedAt。

逻辑删除

java 复制代码
@TableLogic
private Integer deleted;  // 0=未删除, 1=已删除

加了 @TableLogic 之后,removeById 变成 UPDATE SET deleted=1,select 自动加 WHERE deleted=0。数据不真正删除,但可以恢复。

代码生成器

java 复制代码
// 一键生成 Entity + Mapper + Service + Controller
FastAutoGenerator.create("jdbc:mysql://localhost:3306/mydb", "root", "password")
    .globalConfig(builder -> builder
        .author("zhangsan")
        .outputDir("/src/main/java")
    )
    .packageConfig(builder -> builder
        .parent("com.example")
        .moduleName("system")
    )
    .strategyConfig(builder -> builder
        .addInclude("sys_user", "sys_role")  // 指定表
        .entityBuilder().enableLombok()
        .controllerBuilder().enableRestStyle()
        .serviceBuilder().formatServiceFileName("%sService")
    )
    .execute();

新建表之后跑一次代码生成器,CRUD 代码直接就有了。

注意事项

  • 复杂 SQL 还是写 XML:多表关联、复杂子查询,MP 的 Wrapper 表达力有限,该写 SQL 就写
  • Wrapper 的链式调用注意性能:特别长的条件链在极端情况下有性能开销,但一般可以忽略
  • 不要滥用 last():直接拼 SQL 有注入风险,参数必须自己校验

总结

MyBatis-Plus 的价值:单表 CRUD 零 SQL、分页自动化、条件构造器类型安全、自动填充省重复代码、逻辑删除一行注解。复杂查询还是写原生 SQL,两者互补。

相关推荐
大漠孤烟s6 天前
4.Mybatis学习-动态sql、缓存、逆向工程
mybatis
毕业设计7038 天前
(免费领源码) SpringBoot 游戏交易平台17600-java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
java·spring boot·mysql·决策树·mybatis·idea·推荐算法
程序员JerrySUN8 天前
Jetson Edge AI 实战01:Nano、Xavier、Orin 怎么选?Jetson 硬件选型详解【视频讲解】
java·数据库·redis·安全·mybatis
linmengmeng_13148 天前
【总结】MyBatis-Plus批量插入与清表的正确姿势
java·spring boot·mysql·mybatis
vx_BS813309 天前
【项目编号:project51381】Spring Boot 婚纱摄影管理系统:套餐预约、在线咨询、支付与客片展示的一站式业务实现
java·spring boot·eclipse·tomcat·mybatis
jaysee-sjc10 天前
【苍穹外卖】Day01:从零认识企业级项目开发
java·开发语言·数据库·mysql·spring·intellij-idea·mybatis
程序猿乐锅10 天前
【黑马点评 | 第二篇】Redis 缓存更新策略与商铺缓存实现
java·网络·redis·spring·mybatis
萧瑟余晖10 天前
MyBatis 核心原理详解
架构·mybatis
MZA66610 天前
实战:基于 XXL-JOB + 策略模式 + Nacos 配置化的 CSV 导出任务系统设计
java·spring boot·mybatis