完整教程:MyBatis-Plus使用详解
一、什么是 MyBatis-Plus?
MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
核心特性:
无侵入:只做增强不做改变,引入它不会对现有工程产生影响。
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作。
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求。
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错。
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题。
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件后,写分页等同于普通 List 查询。
内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询。
内置全局拦截插件:提供全表
delete、update操作智能分析阻断,也可自定义拦截规则,预防误操作。支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库。
二、快速入门
1. 添加依赖
以 Spring Boot 项目为例,在 pom.xml 中添加:
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-test
test
com.baomidou
mybatis-plus-boot-starter
3.5.6
mysql
mysql-connector-java
8.0.33
org.projectlombok
lombok
true
2. 配置
在 application.yml 中配置数据源和 MyBatis-Plus:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus_demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: root
password: 123456
# MyBatis-Plus 配置
mybatis-plus:
configuration:
# 在控制台打印SQL日志,便于调试
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 全局逻辑删除的实体字段名 (since 3.3.0)
logic-delete-field: deleted
# 逻辑已删除值(默认为 1)
logic-delete-value: 1
# 逻辑未删除值(默认为 0)
logic-not-delete-value: 0
# 主键类型。AUTO-数据库ID自增,INPUT-自行设置,ASSIGN_ID-雪花算法,ASSIGN_UUID-UUID
id-type: ASSIGN_ID
3. 创建实体类
使用 Lombok 注解简化代码。
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sys_user") // 指定表名,如果表名和类名一致(忽略大小写和下划线)可省略
public class User {
/**
* 主键
*/
@TableId(type = IdType.ASSIGN_ID) // 使用雪花算法生成ID
private Long id;
/**
* 用户名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 邮箱
*/
private String email;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT) // 插入时自动填充
private LocalDateTime createTime;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时自动填充
private LocalDateTime updateTime;
/**
* 逻辑删除字段 (0-未删除, 1-已删除)
*/
@TableLogic
private Integer deleted;
}
注解说明:
@TableName:表名注解。@TableId:主键注解。IdType常用值:AUTO:数据库 ID 自增。ASSIGN_ID:雪花算法生成 Long 类型的 ID(默认策略)。ASSIGN_UUID:生成 UUID。
@TableField:字段注解。fill:字段自动填充策略。FieldFill.INSERT(插入时填充),FieldFill.UPDATE(更新时填充),FieldFill.INSERT_UPDATE(插入和更新时都填充)。value:数据库字段名(如果属性名和字段名符合驼峰命名规则,可省略)。
@TableLogic:逻辑删除注解。
4. 创建 Mapper 接口
继承 MyBatis-Plus 提供的 BaseMapper 接口。
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
// 指定对应的实体类
public interface UserMapper extends BaseMapper {
// 此时,已经拥有了 BaseMapper 中所有的基本 CRUD 方法
// 无需编写 XML 文件
}
别忘了在启动类上添加 @MapperScan 注解:
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.demo.mapper") // 扫描 Mapper 接口所在的包
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
5. 测试
编写一个测试类,注入 UserMapper 进行测试。
import com.example.demo.entity.User;
import com.example.demo.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
class DemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void testSelect() {
System.out.println("----- 查询所有用户 ------");
List userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}
@Test
void testInsert() {
User user = new User();
user.setName("张三");
user.setAge(25);
user.setEmail("zhangsan@example.com");
int result = userMapper.insert(user);
System.out.println("插入影响行数: " + result);
System.out.println("生成的主键ID: " + user.getId());
}
@Test
void testUpdate() {
User user = new User();
user.setId(1L);
user.setAge(26);
int result = userMapper.updateById(user);
System.out.println("更新影响行数: " + result);
}
@Test
void testDelete() {
int result = userMapper.deleteById(1L);
System.out.println("删除影响行数: " + result);
}
}
三、核心功能详解
1. 条件构造器 Wrapper
Wrapper 是 MyBatis-Plus 最核心的功能之一,用于构建复杂的 SQL WHERE 条件。推荐使用 LambdaQueryWrapper,避免硬编码字段名。
@Test
void testQueryWrapper() {
// 1. 查询年龄大于20且邮箱不为空的用户
LambdaQueryWrapper wrapper1 = new LambdaQueryWrapper<>();
wrapper1.gt(User::getAge, 20)
.isNotNull(User::getEmail);
List userList1 = userMapper.selectList(wrapper1);
// 2. 查询名字包含"张"且年龄小于30的用户
LambdaQueryWrapper wrapper2 = new LambdaQueryWrapper<>();
wrapper2.like(User::getName, "张")
.lt(User::getAge, 30);
List userList2 = userMapper.selectList(wrapper2);
// 3. 按年龄降序排序
LambdaQueryWrapper wrapper3 = new LambdaQueryWrapper<>();
wrapper3.orderByDesc(User::getAge);
List userList3 = userMapper.selectList(wrapper3);
// 4. 只查询指定的字段 (SELECT id, name FROM user ...)
LambdaQueryWrapper wrapper4 = new LambdaQueryWrapper<>();
wrapper4.select(User::getId, User::getName);
List userList4 = userMapper.selectList(wrapper4);
}
2. 自定义 SQL
对于复杂的多表关联查询,仍然需要编写 XML 或注解形式的 SQL。
Mapper 接口:
public interface UserMapper extends BaseMapper {
// 使用注解方式
@Select("SELECT u.*, d.department_name FROM sys_user u LEFT JOIN sys_department d ON u.dept_id = d.id WHERE u.id = #{id}")
User selectUserWithDepartment(Long id);
// 使用 XML 方式 (推荐复杂SQL)
User selectComplexUser(@Param("ew") Wrapper wrapper);
}
XML 文件 (UserMapper.xml):
3. 分页查询
首先需要配置分页插件。
配置类:
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();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
使用分页:
@Test
void testPage() {
// 参数:当前页,每页大小
Page page = new Page<>(1, 5);
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 20);
// 执行查询
Page userPage = userMapper.selectPage(page, wrapper);
System.out.println("总记录数: " + userPage.getTotal());
System.out.println("总页数: " + userPage.getPages());
System.out.println("当前页数据: ");
userPage.getRecords().forEach(System.out::println);
}
4. 通用 Service
MyBatis-Plus 提供了通用的 IService 接口及其实现类 ServiceImpl,进一步封装了常用服务层操作。
1. 创建 Service 接口:
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.User;
public interface UserService extends IService {
// 可以在这里定义自定义方法
User getCustomUserById(Long id);
}
2. 创建 Service 实现类:
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
@Override
public User getCustomUserById(Long id) {
// 这里可以写复杂的业务逻辑
return this.getById(id);
}
}
3. 使用 Service:
@Autowired
private UserService userService;
@Test
void testService() {
// 保存
User user = new User();
user.setName("李四");
userService.save(user);
// 批量查询
List list = userService.list();
// 链式查询
List users = userService.lambdaQuery()
.gt(User::getAge, 20)
.like(User::getName, "张")
.list();
}
5. 自动填充(如创建时间、更新时间)
实现 MetaObjectHandler 接口。
1. 创建填充处理器:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 插入时自动填充
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
// 更新时自动填充
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
2. 在实体类字段上添加 @TableField 注解(见上文实体类示例)。
6. 逻辑删除
配置好全局逻辑删除(见上文 application.yml 配置)和在实体类字段上添加 @TableLogic 注解后,所有删除操作将自动变为更新操作,将 deleted 字段设置为 1。查询操作会自动带上 deleted = 0 的条件。
userMapper.deleteById(1L); // 实际执行的是 UPDATE user SET deleted=1 WHERE id=1 AND deleted=0
userMapper.selectList(null); // 实际执行的是 SELECT ... FROM user WHERE deleted=0
四、常用配置
一个更完整的 application.yml 配置示例:
mybatis-plus:
# 配置 XML 文件位置
mapper-locations: classpath*:/mapper/**/*.xml
# 配置类型别名包
type-aliases-package: com.example.demo.entity
configuration:
# 开启驼峰命名自动映射
map-underscore-to-camel-case: true
# 日志实现
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置JdbcTypeForNull,解决 updateById(id, null) 时,字段不更新问题
jdbc-type-for-null: 'null'
global-config:
db-config:
# 主键类型
id-type: ASSIGN_ID
# 逻辑删除字段名
logic-delete-field: deleted
# 逻辑已删除值
logic-delete-value: 1
# 逻辑未删除值
logic-not-delete-value: 0
# 表名前缀(如果所有表都有共同前缀,可以在此配置)
# table-prefix: t_
五、总结
MyBatis-Plus 通过以下方式极大地提升了开发效率:
开箱即用:继承
BaseMapper/IService即可获得绝大部分单表 CRUD 方法。条件构造器:使用
LambdaQueryWrapper以 Lambda 形式安全、优雅地构建复杂查询条件。代码生成器(本文未展开):可以快速生成 Entity、Mapper、Service、Controller 等全套代码。
内置插件:分页、性能分析、乐观锁、逻辑删除等常用功能都已内置。
无侵入性:与原生 MyBatis 完美共存,原有代码不受任何影响。
对于大多数业务场景,使用 MyBatis-Plus 可以让你告别简单的 CRUD 编写工作,更专注于核心业务逻辑的实现。

浙公网安备 33010602011771号