My Batis-Plus 使用详解
·
MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率。
一、快速入门
1. 添加依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
2. 配置
在 application.yml 中配置:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 123456
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开启SQL日志
global-config:
db-config:
id-type: auto # 主键策略
3. 创建实体类
@Data
@TableName("user") // 指定表名
public class User {
@TableId(type = IdType.AUTO) // 主键自增
private Long id;
private String name;
private Integer age;
private String email;
}
4. 创建Mapper接口
public interface UserMapper extends BaseMapper<User> {
// 继承BaseMapper即可获得CRUD功能
}
5. 使用示例
@SpringBootTest
class MpDemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
二、核心功能
1. CRUD 接口
插入操作
// 插入一条记录
int insert(User entity);
// 批量插入
int insertBatchSomeColumn(List<User> entityList);
删除操作
// 根据ID删除
int deleteById(Serializable id);
// 根据条件删除
int delete(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
// 批量删除
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
更新操作
// 根据ID更新
int updateById(@Param(Constants.ENTITY) User entity);
// 根据条件更新
int update(@Param(Constants.ENTITY) User entity,
@Param(Constants.WRAPPER) Wrapper<User> updateWrapper);
查询操作
// 根据ID查询
User selectById(Serializable id);
// 查询所有
List<User> selectList(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
// 查询一条记录
User selectOne(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
// 查询数量
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
2. 条件构造器
MyBatis-Plus 提供了强大的条件构造器 Wrapper,包括:
-
QueryWrapper:查询条件构造器 -
UpdateWrapper:更新条件构造器 -
LambdaQueryWrapper:Lambda语法查询构造器 -
LambdaUpdateWrapper:Lambda语法更新构造器
基本使用
// 查询年龄大于18且名字包含"张"的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
.like("name", "张");
List<User> users = userMapper.selectList(wrapper);
Lambda方式(推荐)
LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.gt(User::getAge, 18)
.like(User::getName, "张");
List<User> users = userMapper.selectList(lambdaQuery);
常用条件方法
| 方法 | 说明 | 示例 |
|---|---|---|
| eq | 等于 | eq("name", "张三") |
| ne | 不等于 | ne("name", "张三") |
| gt | 大于 | gt("age", 18) |
| ge | 大于等于 | ge("age", 18) |
| lt | 小于 | lt("age", 30) |
| le | 小于等于 | le("age", 30) |
| between | BETWEEN | between("age", 18, 30) |
| notBetween | NOT BETWEEN | notBetween("age", 18, 30) |
| like | LIKE | like("name", "张") |
| notLike | NOT LIKE | notLike("name", "张") |
| likeLeft | LIKE '%值' | likeLeft("name", "三") |
| likeRight | LIKE '值%' | likeRight("name", "张") |
| isNull | IS NULL | isNull("name") |
| isNotNull | IS NOT NULL | isNotNull("name") |
| in | IN | in("age", Arrays.asList(18, 20, 22)) |
| notIn | NOT IN | notIn("age", Arrays.asList(18, 20)) |
| groupBy | GROUP BY | groupBy("dept_id") |
| orderByAsc | ORDER BY ASC | orderByAsc("age") |
| orderByDesc | ORDER BY DESC | orderByDesc("age") |
3. 分页查询
配置分页插件
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
使用分页
@Test
void testPage() {
// 当前页,每页大小
Page<User> page = new Page<>(1, 2);
// 查询条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 10);
// 执行查询
Page<User> userPage = userMapper.selectPage(page, wrapper);
System.out.println("总记录数:" + userPage.getTotal());
System.out.println("当前页记录:" + userPage.getRecords());
}
4. 自定义SQL
注解方式
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT * FROM user WHERE age > #{age}")
List<User> selectByAge(@Param("age") Integer age);
}
XML方式
1.在 resources/mapper 下创建 UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectByName" resultType="com.example.entity.User">
SELECT * FROM user WHERE name = #{name}
</select>
</mapper>
2.在Mapper接口中添加方法
List<User> selectByName(@Param("name") String name);
5. 逻辑删除
配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 逻辑删除字段名
logic-delete-value: 1 # 逻辑已删除值
logic-not-delete-value: 0 # 逻辑未删除值
实体类添加字段
@TableLogic
private Integer deleted;
使用
执行删除操作时,实际执行的是UPDATE语句:
UPDATE user SET deleted=1 WHERE id=? AND deleted=0
三、高级功能
1. 自动填充
配置
-
实现MetaObjectHandler接口
@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()); } } -
实体类添加注解
@TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;
2. 乐观锁
配置
-
添加插件
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } -
实体类添加版本字段
@Version private Integer version;使用
User user = userMapper.selectById(1L); user.setName("new name"); userMapper.updateById(user); // 会自动带上 version 条件
3. 枚举处理
MyBatis-Plus 提供了完善的枚举处理方案。
方式一:使用枚举属性
public enum GenderEnum {
MALE(1, "男"),
FEMALE(2, "女");
@EnumValue // 标记数据库存储的值
private final int code;
private final String desc;
// 构造方法、getter省略
}
方式二:实现IEnum接口
public enum AgeEnum implements IEnum<Integer> {
ONE(1, "一岁"),
TWO(2, "二岁");
private int value;
private String desc;
@Override
public Integer getValue() {
return this.value;
}
}
4. 多租户
配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 多租户插件
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
// 返回当前租户ID
return new LongValue(1L);
}
@Override
public String getTenantIdColumn() {
// 租户字段名
return "tenant_id";
}
@Override
public boolean ignoreTable(String tableName) {
// 不需要过滤的表
return "tenant".equals(tableName);
}
}));
return interceptor;
}
5. 动态表名
配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor(new TableNameHandler() {
@Override
public String dynamicTableName(String sql, String tableName) {
if ("user".equals(tableName)) {
return "user_" + LocalDate.now().getYear();
}
return tableName;
}
}));
return interceptor;
}
四、代码生成器
MyBatis-Plus 提供了强大的代码生成器:
public class CodeGenerator {
public static void main(String[] args) {
AutoGenerator generator = new AutoGenerator();
// 全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
globalConfig.setAuthor("author");
globalConfig.setOpen(false);
generator.setGlobalConfig(globalConfig);
// 数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mp_demo");
dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
dataSourceConfig.setUsername("root");
dataSourceConfig.setPassword("123456");
generator.setDataSource(dataSourceConfig);
// 包配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.example");
packageConfig.setModuleName("demo");
generator.setPackageInfo(packageConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true);
strategy.setRestControllerStyle(true);
strategy.setInclude("user", "order"); // 要生成的表
generator.setStrategy(strategy);
generator.execute();
}
}
五、最佳实践
-
使用Lambda表达式:避免字段名的硬编码,提高代码可读性和可维护性
-
合理使用分页:大数据量查询一定要使用分页
-
逻辑删除:优先使用逻辑删除而非物理删除
-
自动填充:对于创建时间、更新时间等字段使用自动填充
-
批量操作:大数据量操作使用批量方法提高性能
-
避免N+1问题:使用关联查询或自定义SQL解决
更多推荐


所有评论(0)