Mybatis-Plus基本功能详解
一、为什么选择 MyBatis-Plus?
MyBatis 虽然灵活,但需要手动编写大量 XML 映射文件或注解 SQL,而 MyBatis-Plus 解决了这些痛点:
无侵入:完全兼容 MyBatis,原有代码无需修改即可升级。
CRUD 自动生成:内置通用 Mapper/Service,单表操作无需写 SQL。
强大的条件构造器:支持链式调用,轻松构建复杂查询条件。
自动分页:无需手动处理分页参数,分页查询一键实现。
逻辑删除:无需修改 SQL,自动处理软删除逻辑。
代码生成器:一键生成 Entity、Mapper、Service、Controller 全套代码。
二、环境搭建(Spring Boot 整合)
1. 引入依赖
在 pom.xml 中添加 MyBatis-Plus 核心依赖(以 MySQL 为例):
<!-- Spring Boot 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
<relativePath/>
</parent>
<!-- 核心依赖 -->
<dependencies>
<!-- MyBatis-Plus 核心包 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok(简化实体类) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2. 配置数据库连接
在 application.yml 中配置数据库和 MyBatis-Plus 基本信息:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
# MyBatis-Plus 配置
mybatis-plus:
# 实体类别名包扫描
type-aliases-package: com.example.mpdemo.entity
# 配置 mapper.xml 扫描路径(可选)
mapper-locations: classpath:mapper/**/*.xml
# 日志配置(方便调试)
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 全局配置
global-config:
db-config:
# 主键自增策略
id-type: auto
# 逻辑删除字段名(可选)
logic-delete-field: isDeleted
# 逻辑删除-未删除值
logic-not-delete-value: 0
# 逻辑删除-已删除值
logic-delete-value: 1
3. 启动类添加注解
在 Spring Boot 启动类上添加 @MapperScan,扫描 Mapper 接口包:
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
// 扫描 Mapper 接口所在包
@MapperScan("com.example.mpdemo.mapper")
public class MpDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MpDemoApplication.class, args);
}
}
三、核心功能实战
1. 基础 CRUD 操作(无需写 SQL)
步骤 1:创建实体类
以 User 表为例,使用 Lombok 简化代码:
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data // Lombok 自动生成 getter/setter/toString 等
@TableName("user") // 指定数据库表名(若类名与表名一致可省略)
public class User {
// 主键(对应全局配置的 auto 自增)
@TableId(type = IdType.AUTO)
private Long id;
// 用户名(若字段名与属性名一致可省略 @TableField)
private String username;
// 密码
private String password;
// 年龄
private Integer age;
// 邮箱
private String email;
// 逻辑删除字段
@TableLogic
private Integer isDeleted;
// 创建时间(自动填充)
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
// 更新时间(自动填充)
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
步骤 2:创建 Mapper 接口
继承 BaseMapper,自动获得 CRUD 方法:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mpdemo.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 无需写任何代码,BaseMapper 已包含所有单表 CRUD
}
步骤 3:测试 CRUD 操作
import com.example.mpdemo.entity.User;
import com.example.mpdemo.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class CrudTest {
@Autowired
private UserMapper userMapper;
// 新增
@Test
public void testInsert() {
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
user.setAge(20);
user.setEmail("zhangsan@test.com");
// 插入数据,返回受影响行数
int rows = userMapper.insert(user);
System.out.println("新增成功,受影响行数:" + rows + ",主键ID:" + user.getId());
}
// 查询单个
@Test
public void testSelectById() {
User user = userMapper.selectById(1L);
System.out.println(user);
}
// 查询所有
@Test
public void testSelectList() {
List<User> userList = userMapper.selectList(null); // null 表示无查询条件
userList.forEach(System.out::println);
}
// 更新
@Test
public void testUpdateById() {
User user = new User();
user.setId(1L);
user.setAge(21); // 只更新年龄
int rows = userMapper.updateById(user);
System.out.println("更新成功,受影响行数:" + rows);
}
// 删除(物理删除)
@Test
public void testDeleteById() {
int rows = userMapper.deleteById(1L);
System.out.println("删除成功,受影响行数:" + rows);
}
// 逻辑删除(实际执行 update,将 isDeleted 设为 1)
@Test
public void testLogicDelete() {
int rows = userMapper.deleteById(2L);
System.out.println("逻辑删除成功,受影响行数:" + rows);
}
}
2. 条件构造器(Wrapper):构建复杂查询
QueryWrapper/LambdaQueryWrapper 是 MP 最强大的功能之一,支持链式构建查询条件:
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mpdemo.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class WrapperTest {
@Autowired
private UserMapper userMapper;
// 基础 QueryWrapper(字符串字段名,易出错)
@Test
public void testQueryWrapper() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 年龄大于 18 且用户名包含 "张" 且邮箱不为空
wrapper.gt("age", 18)
.like("username", "张")
.isNotNull("email");
List<User> userList = userMapper.selectList(wrapper);
userList.forEach(System.out::println);
}
// LambdaQueryWrapper(类型安全,推荐)
@Test
public void testLambdaQueryWrapper() {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
// 避免手写字段名,防止拼写错误
wrapper.gt(User::getAge, 18)
.like(User::getUsername, "张")
.isNotNull(User::getEmail);
List<User> userList = userMapper.selectList(wrapper);
userList.forEach(System.out::println);
}
// 分页查询
@Test
public void testPage() {
// 1. 构建分页条件:第 1 页,每页 10 条
Page<User> page = new Page<>(1, 10);
// 2. 构建查询条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 18);
// 3. 执行分页查询
Page<User> resultPage = userMapper.selectPage(page, wrapper);
// 4. 获取分页结果
System.out.println("总记录数:" + resultPage.getTotal());
System.out.println("总页数:" + resultPage.getPages());
System.out.println("当前页数据:");
resultPage.getRecords().forEach(System.out::println);
}
}
3. 自动填充(创建 / 更新时间)
实现 MetaObjectHandler,自动填充创建时间和更新时间:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component // 必须交给 Spring 管理
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时填充
@Override
public void insertFill(MetaObject metaObject) {
// 填充 createTime 和 updateTime
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
// 更新时填充
@Override
public void updateFill(MetaObject metaObject) {
// 只填充 updateTime
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
4. 代码生成器(一键生成全套代码)
MP 提供代码生成器,可快速生成 Entity、Mapper、Service、Controller,减少重复工作。
引入代码生成器依赖:
<!-- MyBatis-Plus 代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 模板引擎(Freemarker) -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
编写生成器代码:
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
public class CodeGenerator {
public static void main(String[] args) {
// 数据库连接配置
String url = "jdbc:mysql://localhost:3306/mp_demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
String username = "root";
String password = "123456";
// 快速生成代码
FastAutoGenerator.create(url, username, password)
// 全局配置
.globalConfig(builder -> {
builder.author("你的名字") // 设置作者
.outputDir(System.getProperty("user.dir") + "/src/main/java") // 输出目录
.enableSwagger() // 开启 Swagger(可选)
.commentDate("yyyy-MM-dd") // 注释日期格式
.disableOpenDir(); // 生成后不打开文件夹
})
// 包配置
.packageConfig(builder -> {
builder.parent("com.example.mpdemo") // 父包名
.moduleName("") // 模块名(无则空)
.entity("entity") // 实体类包名
.mapper("mapper") // Mapper 包名
.service("service") // Service 包名
.controller("controller") // Controller 包名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper")); // Mapper XML 路径
})
// 策略配置
.strategyConfig(builder -> {
builder.addInclude("user") // 要生成的表名(多个用逗号分隔)
.addTablePrefix("t_", "sys_") // 忽略表前缀(如 t_user → User)
// 实体类策略
.entityBuilder()
.enableLombok() // 启用 Lombok
.enableTableFieldAnnotation() // 生成字段注解
// Controller 策略
.controllerBuilder()
.enableRestStyle() // 生成 RestController
.enableHyphenStyle() // URL 中驼峰转连字符(如 userInfo → user-info)
// Service 策略
.serviceBuilder()
.formatServiceFileName("%sService") // Service 命名规则
.formatServiceImplFileName("%sServiceImpl");
})
// 模板引擎(Freemarker)
.templateEngine(new FreemarkerTemplateEngine())
// 执行生成
.execute();
}
}
四、进阶技巧
1. 自定义 SQL
若 MP 内置方法无法满足需求,可自定义 SQL(兼容 MyBatis 写法):
// UserMapper.java
@Select("SELECT * FROM user WHERE age > #{age}")
List<User> selectByAge(@Param("age") Integer age);
// 或在 UserMapper.xml 中编写
<select id="selectByAge" resultType="com.example.mpdemo.entity.User">
SELECT * FROM user WHERE age > #{age}
</select>
2. 多表关联查询
MP 不直接支持多表关联,但可通过 @Select 注解或 XML 实现,结合 Wrapper 灵活拼接条件。
3. 乐观锁
解决并发更新问题,步骤:
实体类添加版本字段 @Version:
@Version
private Integer version;
配置乐观锁插件:
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
更多推荐




所有评论(0)