MyBatis-Plus
约 1087 字大约 4 分钟
布欧-Lewyon
2026-05-15
首页 › Spring Boot › 数据访问 › MyBatis-Plus
MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在 MyBatis 基础上提供通用 CRUD、分页、条件构造器等能力——可以理解为 MyBatis 的"轮子",不改变 MyBatis 核心,仅降低使用成本。
起步依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.9</version>
</dependency>Spring Boot 3.x 使用
mybatis-plus-spring-boot3-starter(包名jakarta.*兼容)。Boot 2.x 使用mybatis-plus-boot-starter。
mybatis-plus:
global-config:
db-config:
id-type: auto # 主键策略:自增
logic-delete-field: deleted # 逻辑删除字段名
logic-delete-value: 1
logic-not-delete-value: 0
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl通用 CRUD(BaseMapper)
MP 的 BaseMapper 提供了开箱即用的 CRUD 方法,无需手写 XML:
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 无需任何方法即可使用:
// insert / deleteById / deleteByMap / updateById / selectById / selectList / selectPage ...
}@Service
public class UserService {
private final UserMapper userMapper;
// 查询单条
public User findById(Long id) {
return userMapper.selectById(id);
}
// 条件查询
public List<User> findByName(String name) {
return userMapper.selectList(
new QueryWrapper<User>().eq("user_name", name));
}
// 分页查询(需要配置分页插件)
public Page<User> page(int current, int size) {
return userMapper.selectPage(
new Page<>(current, size), null);
}
// 新增
public boolean save(User user) {
return userMapper.insert(user) > 0;
}
}条件构造器(QueryWrapper / LambdaQueryWrapper)
// QueryWrapper:列名用字符串(不推荐,重构不友好)
QueryWrapper<User> qw = new QueryWrapper<>();
qw.like("user_name", "张")
.ge("age", 18)
.orderByDesc("created_at")
.last("LIMIT 10");
// LambdaQueryWrapper:列名用方法引用(推荐)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.like(User::getUserName, "张")
.ge(User::getAge, 18)
.orderByDesc(User::getCreatedAt);
List<User> users = userMapper.selectList(lqw);常用条件方法:
| 方法 | 说明 | 示例 |
|---|---|---|
eq | 等于 | eq(User::getAge, 18) |
ne | 不等于 | ne(User::getStatus, 0) |
gt / ge | 大于 / 大于等于 | ge(User::getAge, 18) |
lt / le | 小于 / 小于等于 | lt(User::getAge, 60) |
like | LIKE | like(User::getUserName, "张") |
in | IN | in(User::getAge, 18, 20, 22) |
isNull / isNotNull | NULL 判断 | isNull(User::getEmail) |
orderByAsc / orderByDesc | 排序 | orderByDesc(User::getCreatedAt) |
IService 与 ServiceImpl
IService / ServiceImpl 提供了比 BaseMapper 更丰富的 Service 层方法(批量操作、链表):
public interface UserService extends IService<User> {
// 可在此添加自定义方法
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
implements UserService {
// 直接使用 saveBatch / saveOrUpdate / listByIds / page 等方法
}@Service
public class OrderService {
@Autowired
private UserService userService; // 注入 Service 层
public void batchSave() {
List<User> users = List.of(new User("张三"), new User("李四"));
userService.saveBatch(users); // 批量插入(自动分批)
}
}分页插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
return interceptor;
}
}自动填充(Audit Meta Object Handler)
用于自动填充创建时间、更新时间等通用字段:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, LocalDateTime.now());
this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now());
}
}@Entity
public class User {
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdAt;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedAt;
}代码生成器
MP 的代码生成器可以根据数据库表一键生成 Entity、Mapper、Service、Controller:
FastAutoGenerator.create("jdbc:postgresql://localhost:5432/mydb", "user", "password")
.globalConfig(builder -> builder.author("lewyon").outputDir("src/main/java"))
.packageConfig(builder -> builder.parent("com.example.demo"))
.strategyConfig(builder -> builder.addInclude("users", "orders"))
.execute();生产意识:代码生成器适合项目初期快速搭建骨架,但不建议持续反复运行覆盖——生成的代码应被视为基线,后续手动修改。建议只生成 Entity + Mapper + Service,Controller 层手写以保持 REST 风格一致。
原生 MyBatis vs MyBatis-Plus
| 对比维度 | 原生 MyBatis | MyBatis-Plus |
|---|---|---|
| 基本 CRUD | 手写 SQL + XML | BaseMapper 自动生成 |
| 条件查询 | <where> + <if> 手写 | LambdaQueryWrapper 链式 |
| 分页 | 手写 LIMIT 或用 PageHelper | PaginationInnerInterceptor |
| 批量操作 | BatchExecutor 或 <foreach> | saveBatch(自动分批) |
| 逻辑删除 | 手写 WHERE deleted=0 | @TableLogic 自动拦截 |
| 自动填充 | 无 | MetaObjectHandler |
| 代码生成 | MyBatis Generator | FastAutoGenerator |
| 性能 | 相同(底层都是 MyBatis) | 相同 |
小结
- MyBatis-Plus 在 MyBatis 之上提供 BaseMapper 通用 CRUD、LambdaQueryWrapper 条件构造器、分页插件等能力。
IService+ServiceImpl提供批量操作和 Service 层增强。- 自动填充、逻辑删除、代码生成器减少大量重复代码。
- 与原生 MyBatis 相比,MP 不改变 MyBatis 核心——XML 映射、自定义 SQL 完全兼容。
- 易错:分页插件必须配置
MybatisPlusInterceptor,否则selectPage不会自动拼接分页 SQL。LambdaQueryWrapper的方法引用在编译时需要保留ParameterNameDiscoverer或使用@Param。逻辑删除仅对 MP 的delete方法生效,手写 SQL 中的DELETE不受影响。 - 思考任务:在项目中集成 MyBatis-Plus,使用
BaseMapper+LambdaQueryWrapper改写现有的原生 MyBatis DAO,体验开发效率提升。
上一节:MyBatis
下一节:数据库迁移
