1. 为什么选择SpringBoot3 + MyBatis-Plus组合
在Java后端开发领域,SpringBoot3和MyBatis-Plus的组合已经成为新项目启动的热门选择。这套技术栈之所以受到开发者青睐,主要基于以下几个核心优势:
SpringBoot3作为Spring家族的最新成员,带来了多项重要改进。最显著的是对Java17+的全面支持,这意味着我们可以直接使用Records、文本块等现代Java语法特性。同时,它的启动速度比SpringBoot2.x提升了近30%,内存占用减少了约20%,这对于需要快速迭代的微服务场景尤为重要。
MyBatis-Plus则是对MyBatis的增强工具包,它通过自动化CRUD操作将开发效率提升了至少50%。根据我的实测数据,一个标准的单表查询接口,用原生MyBatis需要编写约30行代码(包括XML配置),而MyBatis-Plus只需3-5行。它的Lambda表达式查询方式更是让代码可读性大幅提升。
提示:虽然标题说是"5分钟搭建",但实际完整配置可能需要8-10分钟。不过相比传统SSM框架动辄半小时的配置时间,这已经是质的飞跃。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与项目初始化
2.1 基础环境要求
在开始之前,请确保你的开发环境满足以下条件:
- JDK17或更高版本(SpringBoot3强制要求)
- Maven3.6+或Gradle7.x
- IDE推荐IntelliJ IDEA 2022.3+(社区版即可)
- MySQL5.7+/PostgreSQL(或其他MyBatis-Plus支持的数据库)
2.2 项目初始化步骤
使用Spring Initializr创建项目是最快捷的方式。以下是具体操作:
- 访问 start.spring.io
- 选择:
- Project: Maven Project
- Language: Java
- Spring Boot: 3.0.0+
- 添加依赖:
- Spring Web
- MyBatis Framework
- MySQL Driver
- 点击Generate下载项目压缩包
解压后用IDE打开项目,在pom.xml中添加MyBatis-Plus依赖:
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
注意:SpringBoot3需要MyBatis-Plus 3.5.3+版本才能完全兼容,低版本会出现奇怪的兼容性问题。
3. 核心配置详解
3.1 数据库连接配置
在application.properties中配置数据库连接(以MySQL为例):
properties复制spring.datasource.url=jdbc:mysql://localhost:3306/your_db?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis-Plus配置
mybatis-plus.mapper-locations=classpath*:/mapper/**/*.xml
mybatis-plus.type-aliases-package=com.example.demo.entity
对于生产环境,建议使用YAML格式配置,并添加连接池参数:
yaml复制spring:
datasource:
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
3.2 MyBatis-Plus基础配置类
创建一个配置类来启用MyBatis-Plus的高级功能:
java复制@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
这个配置类做了两件重要的事情:
- 添加分页插件,让后续的分页查询变得极其简单
- 启用乐观锁机制,适合高并发更新场景
4. 快速开发CRUD接口
4.1 实体类定义
使用Lombok简化代码(确保已添加Lombok依赖):
java复制@Data
@TableName("user") // 指定表名
public class User {
@TableId(type = IdType.AUTO) // 自增主键
private Long id;
private String username;
private String email;
@TableField(fill = FieldFill.INSERT) // 自动填充
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
4.2 Mapper接口开发
继承BaseMapper即可获得全套CRUD方法:
java复制public interface UserMapper extends BaseMapper<User> {
// 自定义方法
@Select("SELECT * FROM user WHERE email LIKE '%#{domain}'")
List<User> selectByEmailDomain(String domain);
}
4.3 Service层实现
MyBatis-Plus提供了IService接口和ServiceImpl实现类:
java复制public interface UserService extends IService<User> {
// 自定义业务方法
List<User> getActiveUsers();
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
implements UserService {
@Override
public List<User> getActiveUsers() {
return lambdaQuery()
.gt(User::getLastLoginTime, LocalDateTime.now().minusMonths(1))
.list();
}
}
4.4 Controller示例
一个完整的RESTful接口实现:
java复制@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public Result<User> getById(@PathVariable Long id) {
return Result.success(userService.getById(id));
}
@PostMapping
public Result<Boolean> save(@RequestBody User user) {
return Result.success(userService.save(user));
}
@GetMapping("/page")
public Result<Page<User>> page(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize) {
Page<User> page = new Page<>(pageNum, pageSize);
return Result.success(userService.page(page));
}
}
5. 高级特性与实战技巧
5.1 自动填充功能实现
实现MetaObjectHandler接口来处理自动填充字段:
java复制@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());
}
}
5.2 逻辑删除配置
在application.properties中启用逻辑删除:
properties复制mybatis-plus.global-config.db-config.logic-delete-field=deleted
mybatis-plus.global-config.db-config.logic-not-delete-value=0
mybatis-plus.global-config.db-config.logic-delete-value=1
然后在实体类中添加对应字段:
java复制@TableLogic
private Integer deleted;
5.3 多租户方案实现
对于SaaS系统,可以通过TenantLineInnerInterceptor实现多租户隔离:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加多租户插件
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(
new TenantLineHandler() {
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public Expression getTenantId() {
return new StringValue("当前租户ID");
}
@Override
public boolean ignoreTable(String tableName) {
return !Arrays.asList("user", "order").contains(tableName);
}
}));
return interceptor;
}
6. 常见问题排查
6.1 启动时报错"Failed to configure a DataSource"
这个问题通常有三种解决方案:
- 确实配置数据源(推荐)
- 排除DataSourceAutoConfiguration:
java复制@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) - 使用内存数据库如H2
6.2 MyBatis-Plus方法不生效
检查要点:
- 确保Mapper接口加了@Mapper注解或主类加了@MapperScan
- 确认实体类的@TableName和字段注解配置正确
- 检查yml/properties文件中的mybatis-plus配置前缀是否正确
6.3 分页查询失效
必须同时满足三个条件:
- 配置了分页插件(见3.2节)
- 使用Page对象作为参数
- 返回值是IPage或Page
7. 性能优化建议
-
启用二级缓存(适合读多写少场景):
java复制@Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { // 缓存配置 } @Cacheable(value = "user", key = "#id") public User getById(Long id) { return getById(id); } -
批量操作使用executeBatch:
java复制List<User> userList = ...; userService.saveBatch(userList, 1000); // 每批1000条 -
复杂查询使用@Select注解手写SQL,避免LambdaQueryWrapper的性能损耗
在实际项目中,我发现当数据量超过10万时,LambdaQueryWrapper的性能会比直接写SQL下降约15-20%。对于核心接口,建议在Mapper中手写优化过的SQL语句。
