一、MyBatis-Plus 核心优势
- 无侵入:只增强 MyBatis 功能,原有 MyBatis 代码不受任何影响,平滑迁移;
- 内置通用 Mapper:BaseMapper 封装单表增删改查,无需写 XML;
- 强大条件构造器:Wrapper 自动拼接动态 SQL,不用拼接字符串;
- 内置分页插件:一行代码实现分页,支持多数据库;
- 逻辑删除、乐观锁、主键策略开箱即用;
- 代码生成器:一键生成 Entity、Mapper、Service、Controller 全套代码;
- 支持多种数据库:MySQL、Oracle、PostgreSQL、SQLServer 等主流数据库。
二、SpringBoot 整合 MyBatis-Plus
2.1 Maven 依赖引入
xml
<!-- SpringBoot 父工程自行引入 -->
<!-- MyBatis-Plus 启动器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 数据库连接池 HikariCP(SpringBoot默认) -->
<!-- lombok简化实体类get/set -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2.2 application.yml 配置文件
yaml
# 数据库配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 你的数据库密码
# MyBatis-Plus配置
mybatis-plus:
# 实体类别名包路径
type-aliases-package: com.example.mp.entity
# mapper映射文件位置
mapper-locations: classpath:mapper/*.xml
configuration:
# 开启SQL打印日志,开发调试必备
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 开启驼峰命名自动转换:数据库user_name → 实体userName
map-underscore-to-camel-case: true
global-config:
db-config:
# 主键自增策略
id-type: auto
# 逻辑删除字段名
logic-delete-field: isDeleted
logic-delete-value: 1 # 删除值
logic-not-delete-value: 0 # 未删除值
2.3 启动类添加 Mapper 扫描注解
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
// 扫描mapper接口所在包
@MapperScan("com.example.mp.mapper")
public class MpApplication {
public static void main(String[] args) {
SpringApplication.run(MpApplication.class, args);
}
}
三、实体类、Mapper、Service 基础结构
3.1 数据库表设计(user 表)
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_name` varchar(30) DEFAULT NULL COMMENT '用户名',
`age` int DEFAULT NULL COMMENT '年龄',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`version` int DEFAULT 1 COMMENT '乐观锁版本号',
`is_deleted` tinyint DEFAULT 0 COMMENT '逻辑删除 0未删 1已删',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 实体类 User.java
使用 MP 注解映射表、字段,Lombok 简化代码
package com.example.mp.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@Data
@TableName("user") // 映射数据库user表
public class User {
// 主键自增
@TableId(type = IdType.AUTO)
private Long id;
@TableField("user_name")
private String userName;
private Integer age;
private String email;
// 乐观锁版本字段
@Version
private Integer version;
// 逻辑删除字段
@TableLogic
private Integer isDeleted;
}
3.3 Mapper 接口(核心 BaseMapper)
继承BaseMapper<T>,自动获得单表所有 CRUD 方法,无需写 XML
package com.example.mp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mp.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 内置方法:insert、deleteById、updateById、selectById、selectList等
}
3.4 Service 层(可选,封装业务)
MP 提供ServiceImpl实现类,封装批量操作、分页查询
// Service接口
public interface UserService extends IService<User> {
}
// Service实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
四、内置通用 CRUD 操作(BaseMapper)
4.1 新增 insert
@Autowired
private UserMapper userMapper;
@Test
void testInsert(){
User user = new User();
user.setUserName("张三");
user.setAge(20);
user.setEmail("zhangsan@163.com");
// 返回受影响行数,自动回填自增id
int rows = userMapper.insert(user);
System.out.println("新增行数:"+rows);
System.out.println("自增主键id:"+user.getId());
}
4.2 根据 id 查询 selectById
User user = userMapper.selectById(1L);
System.out.println(user);
4.3 根据 id 更新 updateById
只更新实体中非 null 字段,不会覆盖原有数据
User updateUser = new User();
updateUser.setId(1L);
updateUser.setAge(22);
userMapper.updateById(updateUser);
4.4 根据 id 删除 deleteById
userMapper.deleteById(1L);
4.5 批量操作(IService 提供)
@Autowired
private UserService userService;
// 批量新增
List<User> batchList = new ArrayList<>();
userService.saveBatch(batchList);
// 批量删除
userService.removeByIds(Arrays.asList(1L,2L,3L));
五、条件构造器 Wrapper
5.1 QueryWrapper 条件查询
// 查询:年龄大于18,名字包含"张",按id降序
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
.like("user_name", "张")
.orderByDesc("id");
List<User> list = userMapper.selectList(wrapper);
5.2 LambdaQueryWrapper
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.gt(User::getAge, 18)
.like(User::getUserName, "张")
.orderByDesc(User::getId);
List<User> list = userMapper.selectList(lambdaWrapper);
5.3 UpdateWrapper 条件更新
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("age",20)
.set("email", "update@qq.com");
userMapper.update(null, updateWrapper);
六、分页插件配置与分页查询
6.1 分页插件配置类
package com.example.mp.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件,指定数据库类型MySQL
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
6.2 分页查询代码
// 参数1:当前页,参数2:每页条数
Page<User> page = new Page<>(1,5);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
// page接收分页结果,自动封装总条数、总页数、当前页数据
Page<User> resultPage = userMapper.selectPage(page, wrapper);
System.out.println("总记录数:"+resultPage.getTotal());
System.out.println("当前页数据:"+resultPage.getRecords());
七、高级功能
7.1 逻辑删除
配置文件已开启全局逻辑删除,调用deleteById不会真实删除数据,自动执行update set is_deleted=1,查询时自动过滤已删除数据。
// 逻辑删除,底层执行update语句
userMapper.deleteById(1L);
7.2 乐观锁(解决并发更新丢失)
场景:多线程同时修改同一条数据,避免覆盖更新,通过 version 版本号实现。
-
实体添加
@Version注解 -
配置类添加乐观锁插件
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); -
更新逻辑:更新时校验 version,匹配成功 version+1,失败更新行数为 0
User user = userMapper.selectById(1L);
user.setAge(30);
userMapper.updateById(user);
八、MyBatis-Plus 代码生成器
生成器依赖
xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
生成器测试类
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import java.util.Collections;
public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/test_db?serverTimezone=Asia/Shanghai", "root", "数据库密码")
.globalConfig(builder -> {
builder.author("作者名") // 设置作者
.outputDir(System.getProperty("user.dir") + "/src/main/java"); // 输出路径
})
.packageConfig(builder -> {
builder.parent("com.example.mp") // 父包名
.moduleName("") // 模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
builder.addInclude("user") // 要生成的表名
.entityBuilder()
.enableLombok() // 开启lombok
.tableAnnotateEnable(true); // 开启表注解
})
.execute();
}
}
九、总结
- 分页查询 total 为 0 :忘记配置
PaginationInnerInterceptor分页插件; - LambdaWrapper 报字段不存在 :实体字段和数据库映射错误,检查
@TableField; - 逻辑删除不生效 :yml 未配置 logic-delete 相关参数,实体缺少
@TableLogic; - 乐观锁更新失效:未添加乐观锁插件、更新时没有携带 version 字段;
- SQL 驼峰转换失效 :yml 关闭了
map-underscore-to-camel-case; - Mapper 注入报错 :启动类缺少
@MapperScan注解或包路径写错。
MyBatis-Plus 简化了 MyBatis 重复 CRUD 开发,核心使用流程:
- 引入 MP 依赖,配置数据库与 MP 参数;
- 实体类使用注解映射数据表;
- Mapper 继承 BaseMapper 获得通用 CRUD;
- LambdaWrapper 构造动态查询条件;
- 分页、逻辑删除、乐观锁按需开启插件;
- 代码生成器一键生成全套业务代码。
原生 MyBatis 复杂多表联查仍可以自定义 XML,MP 完全兼容,兼顾简单单表快速开发和复杂 SQL 自定义需求。