一、MyBatis-Plus简介
MyBatis-Plus是MyBatis的增强工具包,在保留原生MyBatis特性的基础上,提供了多项开箱即用的功能:
- 自动生成基础CRUD操作
- 内置代码生成器
- 强大的条件构造器Wrapper
- 支持Lambda形式调用
- 主键自动生成策略(支持雪花算法、UUID等)
二、环境搭建与配置
1. 创建SpringBoot项目
使用Spring Initializr创建项目时选择以下依赖:
- Spring Web
- MyBatis-Plus(推荐3.5.3.1及以上版本)
- MySQL Driver
- Lombok(可选,简化代码)
2. 添加依赖
对于SpringBoot3项目(参考若依框架配置):
在父级pom.xml中添加:
<!-- springboot3 / mybatis-plus 配置 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>Latest Version</version>
</dependency>
如果common模块也需要,确保在common模块中也添加相同依赖。
对于SpringBoot2项目:
在pom.xml中添加:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>Latest Version</version>
</dependency>
如果引用的版本大于3.5.9
需要额外的引用
因为 jsqlparser 5.0+
版本不再支持 jdk8
针对这个问题mybatis-plus进行了解耦 jsqlparser
依赖
- jdk11+
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
<version>Latest Version</version>
</dependency>
- jdk8
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
<version>Latest Version</version>
</dependency>
注意事项
引入
MyBatis-Plus
之后请不要再次引入MyBatis
以及mybatis-spring-boot-starter
和MyBatis-Spring
,以避免因版本差异导致的问题。自3.5.4开始,在没有使用
mybatis-plus-boot-starter
或mybatis-plus-spring-boot3-starter
情况下,请自行根据项目情况引入mybatis-spring
。
3. 数据库配置
在application.yml中配置数据库连接信息:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC
username: your_username
password: your_password
# MyBatis Plus配置
mybatis-plus:
# 搜索指定包别名
typeAliasesPackage: com.yourpackage.**.domain
# 配置mapper的扫描,找到所有的mapper.xml映射文件
mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件
configLocation: classpath:mybatis/mybatis-config.xml
# 日志实现(可选)
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 全局配置(可选)
global-config:
db-config:
id-type: assign_id # 主键生成策略
或者在application.properties中配置:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC
spring.datasource.username=your_username
spring.datasource.password=your_password
# MyBatis-Plus配置
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.global-config.db-config.id-type=assign_id
三、MyBatis-Plus配置类
1. MyBatis全局配置
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 数据权限
mybatisPlusInterceptor.addInnerInterceptor(new DataScopeInnerInterceptor());
// 分页插件
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
// 乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 防止全表更新与删除
mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return mybatisPlusInterceptor;
}
@Bean
public FieldMetaObjectHandler fieldMetaObjectHandler(){
return new FieldMetaObjectHandler();
}
}
自动填充字段(可根据需要进行删减)
public class FieldMetaObjectHandler implements MetaObjectHandler {
private final static String CREATE_TIME = "createTime";
private final static String CREATOR = "creator";
private final static String UPDATE_TIME = "updateTime";
private final static String UPDATER = "updater";
private final static String DELETED = "deleted";
private final static String ORG_ID = "orgId";
private final static String TENANT_ID = "tenantId";
private final static String VERSION = "version";
@Override
public void insertFill(MetaObject metaObject) {
UserDetail user = SecurityUser.getUser();
LocalDateTime now = LocalDateTime.now();
// 用户字段填充
if (user != null) {
// 创建者
setFieldValByName(CREATOR, user.getId(), metaObject);
// 更新者
setFieldValByName(UPDATER, user.getId(), metaObject);
// 创建者所属机构
setFieldValByName(ORG_ID, user.getOrgId(), metaObject);
// 创建者所属租户
if(ObjectUtil.isEmpty(getFieldValByName(TENANT_ID, metaObject))){
setFieldValByName(TENANT_ID, user.getTenantId(), metaObject);
}
}
// 创建时间
setFieldValByName(CREATE_TIME, now, metaObject);
// 更新时间
setFieldValByName(UPDATE_TIME, now, metaObject);
// 版本号
setFieldValByName(VERSION, 0, metaObject);
// 删除标识
setFieldValByName(DELETED, 0, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
// 更新者
setFieldValByName(UPDATER, SecurityUser.getUserId(), metaObject);
// 更新时间
setFieldValByName(UPDATE_TIME, LocalDateTime.now(), metaObject);
}
}
四、基础结构搭建
1. 实体类定义
使用Lombok简化代码:
@Data
@TableName("t_user") // 指定表名
public class User {
@TableId(type = IdType.ASSIGN_ID) // 主键生成策略
private Long id;
private String username;
private Integer age;
private String email;
@TableField("create_time") // 指定字段名
private LocalDateTime createTime;
}
2. Mapper接口开发
public interface UserMapper extends BaseMapper<User> {
// 继承BaseMapper后已包含基本的CRUD方法
// 可以在此添加自定义SQL方法
}
3. 服务层实现
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 继承ServiceImpl后已包含基本的CRUD方法
// 可以在此添加自定义业务逻辑
}
public interface UserService extends IService<User> {
// 可以在此定义自定义业务方法
}
五、完整CRUD实现案例
1. 控制器层
@RestController
@RequestMapping("/users")
public class UserController {
@Resource
private UserService userService;
// 单个新增
@PostMapping
public Result addUser(@RequestBody User user) {
return Result.success(userService.save(user));
}
// 批量新增
@PostMapping("/batch")
public Result batchAdd(@RequestBody List<User> users) {
return Result.success(userService.saveBatch(users));
}
// 查询所有
@GetMapping
public Result getAllUsers() {
return Result.success(userService.list());
}
// 根据ID查询
@GetMapping("/{id}")
public Result getUserById(@PathVariable Long id) {
return Result.success(userService.getById(id));
}
// 更新
@PutMapping
public Result updateUser(@RequestBody User user) {
return Result.success(userService.updateById(user));
}
// 删除
@DeleteMapping("/{id}")
public Result deleteUser(@PathVariable Long id) {
return Result.success(userService.removeById(id));
}
// 分页查询
@GetMapping("/page")
public Result getUserPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
Page<User> page = new Page<>(pageNum, pageSize);
return Result.success(userService.page(page));
}
}
2. 分页查询示例
@GetMapping("/page")
public Result getUserPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
// 创建分页对象
Page<User> page = new Page<>(pageNum, pageSize);
// 可以添加查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(StringUtils.isNotBlank(name), User::getUsername, name);
// 执行分页查询
Page<User> result = userService.page(page, queryWrapper);
return Result.success(result);
}
六、常见问题解决
-
版本冲突问题:
- 确保mybatis-plus与mybatis版本兼容,引入
MyBatis-Plus
之后最好不要再次引入MyBatis
以及mybatis-spring-boot-starter
和MyBatis-Spring
,以避免因版本差异导致的问题。 - 特别是SpringBoot3项目,必须使用mybatis-plus-spring-boot3-starter
- 确保mybatis-plus与mybatis版本兼容,引入
-
分页失效问题:
- 检查是否正确配置了分页插件
- 确保没有其他拦截器影响了分页功能
-
动态表名不生效:
- 检查DynamicTableNameInnerInterceptor配置是否正确
- 确保TABLE_NAME ThreadLocal被正确设置
-
SQL日志不打印:
- 检查mybatis-plus.configuration.log-impl配置
- 确保日志级别设置为DEBUG
七、总结
通过以上步骤,我们完成了SpringBoot与MyBatis-Plus的集成配置。MyBatis-Plus大大简化了数据库操作,提供了丰富的功能如分页、乐观锁、动态表名等,可以显著提高开发效率。在实际项目中,可以根据需求进一步扩展和定制配置。