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,两者互补。

相关推荐
毕业设计70318 小时前
(免费领源码)SSM董家湾线上点餐系统04682- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
java·redis·mysql·tomcat·maven·mybatis·ssm
云絮.2 天前
mybatis(二)
java·数据库·mybatis
夕除3 天前
redis--主从还是集群,内存
java·spring·mybatis
驭渊的小故事3 天前
MyBatis-Plus 实战指南:从基础 CRUD 到条件构造器与自定义 SQL(二)
数据库·sql·mybatis
毕业设计7034 天前
(免费领源码)基于node的学生公寓管理系统06412- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
vue.js·mysql·node.js·maven·mybatis·express·b/s
驭渊的小故事4 天前
MyBatis XML 开发实战:从配置到 CRUD 全解析
xml·java·mybatis
云絮.5 天前
Mybatis(一)
java·数据库·mybatis
她的男孩7 天前
权限通了、列表有数,一点分页就炸Forge Admin 用 COUNT(1) 扛住复杂待办
java·spring boot·mybatis
paopaokaka_luck7 天前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
大牧师8 天前
Mybatis 框架教程
java·数据库·mybatis·数据持久化·orm