MyBatis-Plus(简称 MP)是在 MyBatis 基础上的增强工具,在 MyBatis 的基础上只做增强不做改变,支持自动生成 SQL、CRUD 接口封装、条件构造等功能,减少重复代码编写,简化开发、提高效率。
一、入门使用
1.环境搭建(Spring Boot 为例)
步骤 1:引入依赖
在pom.xml中添加 MyBatis-Plus 和数据库驱动依赖:
<!-- 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>
步骤 2:配置数据库
在application.yml中配置数据源:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
username: {username} # 替换为实际用户名
password: {password} # 替换为实际密码
driver-class-name: com.mysql.cj.jdbc.Driver
# MyBatis-Plus配置(可选)
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # Mapper.xml路径
type-aliases-package: com.example.entity # 实体类包路径
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志
步骤 3:定义实体类
使用注解映射数据库表和字段:
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("user") // 映射数据库表名
public class User {
@TableId(type = IdType.AUTO) // 主键自增
private Long id;
private String name;
private Integer age;
private String email;
// 省略getter、setter
}
步骤 4:创建 Mapper 接口
继承 MyBatis-Plus 的BaseMapper,自动获得 CRUD 方法:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.User;
public interface UserMapper extends BaseMapper<User> {
// 无需编写方法,BaseMapper已提供基本CRUD
}
步骤 5:启动类添加注解
添加@MapperScan指定 Mapper 接口路径:
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.mapper") // 扫描Mapper接口
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
步骤 6:测试基本 CRUD
通过@Autowired注入UserMapper,直接调用方法:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import java.util.List;
@SpringBootTest
public class UserTest {
@Autowired
private UserMapper userMapper;
// 新增
@Test
public void testInsert() {
User user = new User();
user.setName("张三");
user.setAge(20);
user.setEmail("zhangsan@example.com");
userMapper.insert(user); // 自动生成INSERT语句
}
// 查询所有
@Test
public void testSelectAll() {
List<User> users = userMapper.selectList(null); // null表示无查询条件
users.forEach(System.out::println);
}
}
二、核心功能
1. CRUD 接口封装
MyBatis-Plus 提供了BaseMapper(Mapper 层)和IService(Service 层)两套 CRUD 接口,无需手动编写 SQL:
- BaseMapper:包含
insert、deleteById、updateById、selectById、selectList等方法。 - IService:进一步封装批量操作(如
saveBatch、removeByIds)和复杂查询,需配合ServiceImpl使用:
// Service接口
public interface UserService extends IService<User> {}
// Service实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
2. 条件构造器(Wrapper)
用于动态构建 SQL 条件,避免手动拼接 SQL,核心类包括QueryWrapper(查询条件)和UpdateWrapper(更新条件)。
示例:查询年龄大于 18 且姓名包含 "张" 的用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18) // 年龄>18
.like("name", "张"); // 姓名like '%张%'
List<User> users = userMapper.selectList(queryWrapper);
Lambda 条件构造器(更安全,避免字段名硬编码):
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.gt(User::getAge, 18) // 直接使用实体类方法,避免字段名写错
.like(User::getName, "张");
List<User> users = userMapper.selectList(lambdaWrapper);
3. 主键生成策略
通过@TableId的type属性指定主键生成方式,常用策略:
IdType.AUTO:数据库自增(需数据库表主键设为自增)。IdType.ASSIGN_ID:默认策略,生成雪花算法 ID(Long 类型,适合分布式场景)。IdType.INPUT:手动输入主键。
4. 自动填充
通过@TableField(fill = ...)注解实现字段自动填充(如创建时间、更新时间)。
步骤 1:实体类添加注解:
public class User {
// ...
@TableField(fill = FieldFill.INSERT) // 插入时填充
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时填充
private LocalDateTime updateTime;
}
步骤 2:实现填充处理器:
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) {
// 插入时自动填充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());
}
}
5. 逻辑删除
通过标记字段实现 "假删除"(而非物理删除),避免数据丢失。
步骤 1:实体类添加注解:
public class User {
// ...
@TableLogic // 逻辑删除标记
private Integer deleted; // 0-未删除,1-已删除
}
步骤 2:配置全局逻辑删除(可选):
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 全局逻辑删除字段名
logic-delete-value: 1 # 已删除值
logic-not-delete-value: 0 # 未删除值
效果:调用deleteById时,会自动生成UPDATE user SET deleted=1 WHERE id=?,查询时自动过滤deleted=0的数据。
三、扩展功能
1. 代码生成器
通过AutoGenerator自动生成实体类、Mapper、Service、Controller 等代码,减少重复劳动。
依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 模板引擎(可选,默认Velocity) -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
生成代码示例:
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
public class CodeGenerator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/test", "username", "password")
.globalConfig(builder -> {
builder.author("yourname") // 作者
.outputDir(System.getProperty("user.dir") + "/src/main/java"); // 输出路径
})
.packageConfig(builder -> {
builder.parent("com.example") // 父包名
.moduleName("demo") // 模块名
.entity("entity") // 实体类包名
.mapper("mapper"); // Mapper包名
})
.strategyConfig(builder -> {
builder.addInclude("user") // 要生成的表名
.entityBuilder().enableLombok(); // 启用Lombok
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker模板
.execute();
}
}
2. Active Record(AR 模式)
让实体类继承Model,直接通过实体对象调用 CRUD 方法,简化代码:
public class User extends Model<User> { // 继承Model
// ... 字段和注解
public static void main(String[] args) {
User user = new User();
user.setName("李四");
user.setAge(25);
user.insert(); // 直接调用insert方法
User queryUser = new User();
queryUser.setId(1L);
queryUser.selectById(); // 查询ID=1的用户
}
}
3. 多数据源
通过dynamic-datasource-spring-boot-starter实现多数据源切换,支持主从库、读写分离。
依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
配置:
spring:
datasource:
dynamic:
primary: master # 默认数据源
datasource:
master: # 主库
url: jdbc:mysql://localhost:3306/master
username: {username}
password: {password}
slave: # 从库
url: jdbc:mysql://localhost:3306/slave
username: {username}
password: {password}
使用:通过@DS注解指定数据源:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@DS("master") // 使用主库
public void addUser(User user) {
userMapper.insert(user);
}
@DS("slave") // 使用从库
public List<User> getUserList() {
return userMapper.selectList(null);
}
}
四、常用插件
1. 分页插件
实现物理分页(而非内存分页),支持 MySQL、Oracle 等数据库。
配置:
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;
}
}
使用:
// 分页查询:第1页,每页10条
Page<User> page = new Page<>(1, 10);
// 条件:年龄>18
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 18);
// 执行分页查询
IPage<User> userPage = userMapper.selectPage(page, wrapper);
// 结果
List<User> records = userPage.getRecords(); // 本页数据
long total = userPage.getTotal(); // 总条数
long pages = userPage.getPages(); // 总页数
2. 乐观锁插件
解决并发更新冲突,通过版本号控制(更新时检查版本号,不一致则更新失败)。
配置:
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
使用:
public class User {
// ...
@Version // 版本号字段
private Integer version;
}
// 测试乐观锁
@Test
public void testOptimisticLock() {
// 1. 查询用户(获取当前version=1)
User user = userMapper.selectById(1L);
// 2. 修改用户
user.setAge(21);
// 3. 更新(自动生成WHERE id=? AND version=1,同时version+1)
userMapper.updateById(user);
}
3. 其他插件
- 性能分析插件:输出 SQL 执行时间,用于优化(仅开发环境使用)。
- 防 SQL 注入插件:增强 SQL 安全性(默认开启)。
五、记一记
1. MyBatis 和 MyBatis-Plus 的区别?
- MyBatis:需要手动编写 XML 或注解 SQL,功能基础。
- MyBatis-Plus:在 MyBatis 基础上增强,提供 CRUD 接口、条件构造器、分页等功能,减少 SQL 编写。
2. MyBatis-Plus 的核心注解有哪些?
@TableName:映射数据库表名。@TableId:指定主键,配置生成策略。@TableField:映射非主键字段,配置自动填充等。@TableLogic:标记逻辑删除字段。@Version:标记乐观锁版本号字段。3. 条件构造器中
eq和allEq的区别?
eq("name", "张三"):单个字段等于条件(name = '张三')。allEq({{"name", "张三"}, {"age", 20}}):多个字段等于条件(name = '张三' AND age = 20)。4. 分页插件的原理?
MyBatis-Plus 分页插件通过拦截 SQL,根据数据库类型自动拼接分页语句(如 MySQL 的
LIMIT,Oracle 的ROWNUM),实现物理分页。5. 逻辑删除的实现原理?
- 删除时:拦截
delete方法,改为执行UPDATE语句(更新逻辑删除字段)。- 查询时:自动在
WHERE后添加逻辑删除字段=未删除值的条件。6. 如何自定义 SQL?
- 在 Mapper 接口中定义方法,通过
@Select等注解编写 SQL。- 在 Mapper.xml 中编写 SQL,通过
namespace关联 Mapper 接口。7. MyBatis-Plus 的代码生成器能生成哪些文件?
实体类、Mapper 接口、Mapper.xml、Service 接口、Service 实现类、Controller。
2502

被折叠的 条评论
为什么被折叠?



