1. SpringBoot与MybatisPlus整合的价值与场景
在Java企业级开发中,数据持久层框架的选择直接影响开发效率和系统性能。MybatisPlus作为Mybatis的增强工具,与SpringBoot的自动配置特性结合后,能显著简化CRUD操作和复杂查询的实现。我最近在电商后台系统中采用这种技术组合,单表操作代码量减少了60%,动态查询的响应时间优化了40%左右。
这种组合特别适合需要快速迭代的中小型项目,比如:
- 管理后台系统(权限管理、内容管理)
- 数据报表类应用
- 需要复杂条件查询的业务系统
- 需要快速原型验证的创业项目
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与项目初始化
2.1 基础环境配置
推荐使用以下环境组合(实测最稳定):
xml复制<properties>
<java.version>17</java.version>
<spring-boot.version>3.1.5</spring-boot.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
</properties>
注意:SpringBoot 3.x需要JDK17+,如果团队仍在使用JDK8,需降级到SpringBoot 2.7.x版本
2.2 依赖引入关键点
在pom.xml中需要特别注意的依赖:
xml复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- 代码生成器(非必须但推荐) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.version}</version>
<scope>provided</scope>
</dependency>
3. 核心配置详解
3.1 数据源配置最佳实践
application.yml配置示例:
yaml复制spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
hikari:
maximum-pool-size: 20
minimum-idle: 5
3.2 MybatisPlus专属配置
必须添加的MP配置项:
yaml复制mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # SQL日志输出
global-config:
db-config:
id-type: auto # 主键策略
logic-delete-field: deleted # 逻辑删除字段
logic-delete-value: 1
logic-not-delete-value: 0
4. 实体与Mapper开发
4.1 智能实体类设计
使用注解驱动实体定义:
java复制@Data
@TableName("sys_user") // 表名映射
public class User {
@TableId(type = IdType.AUTO) // 主键策略
private Long id;
@TableField("username") // 字段映射
private String name;
@TableField(fill = FieldFill.INSERT) // 自动填充
private LocalDateTime createTime;
}
4.2 Mapper接口的进化写法
对比传统Mybatis的Mapper改进:
java复制public interface UserMapper extends BaseMapper<User> {
// 已经内置了17个通用方法
// 自定义复杂查询
@Select("SELECT * FROM sys_user WHERE status = #{status}")
List<User> selectByStatus(@Param("status") Integer status);
}
5. 服务层开发技巧
5.1 通用Service封装
MP提供的Service层增强:
java复制public interface UserService extends IService<User> {
// 扩展方法
List<User> findActiveUsers();
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
implements UserService {
@Override
public List<User> findActiveUsers() {
return lambdaQuery()
.eq(User::getStatus, 1)
.list();
}
}
5.2 Lambda表达式查询
更安全的查询写法示例:
java复制public List<User> searchUsers(String keyword, Integer status) {
return lambdaQuery()
.like(StringUtils.isNotBlank(keyword), User::getName, keyword)
.eq(status != null, User::getStatus, status)
.between(User::getCreateTime,
LocalDateTime.now().minusDays(7),
LocalDateTime.now())
.orderByDesc(User::getId)
.list();
}
6. 高级特性实战
6.1 自动填充功能实现
实现MetaObjectHandler处理自动填充:
java复制@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime",
LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime",
LocalDateTime.class, LocalDateTime.now());
}
}
6.2 分页插件配置
分页查询完整实现流程:
java复制@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
// 使用示例
public Page<User> getUserPage(Integer pageNum, Integer pageSize) {
Page<User> page = new Page<>(pageNum, pageSize);
return userMapper.selectPage(page, null);
}
7. 代码生成器应用
7.1 快速生成基础代码
代码生成器配置示例:
java复制public class CodeGenerator {
public static void main(String[] args) {
AutoGenerator generator = new AutoGenerator();
// 数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder(
"jdbc:mysql://localhost:3306/demo",
"root",
"123456")
.build();
// 全局配置
GlobalConfig globalConfig = new GlobalConfig.Builder()
.outputDir(System.getProperty("user.dir") + "/src/main/java")
.author("developer")
.openDir(false)
.build();
// 包配置
PackageConfig packageConfig = new PackageConfig.Builder()
.parent("com.example.demo")
.moduleName("system")
.entity("entity")
.mapper("mapper")
.build();
generator.strategy(
new StrategyConfig.Builder()
.addInclude("sys_user", "sys_role") // 生成哪些表
.entityBuilder()
.enableLombok()
.logicDeleteColumnName("deleted")
.build()
).execute();
}
}
8. 性能优化与问题排查
8.1 常见性能瓶颈
通过EXPLAIN分析慢查询:
sql复制EXPLAIN SELECT * FROM sys_user WHERE status = 1 ORDER BY create_time DESC;
8.2 典型问题解决方案
- 分页查询总数不准
java复制// 关闭count查询
Page<User> page = new Page<>(1, 10);
page.setSearchCount(false);
- 逻辑删除与唯一索引冲突
yaml复制mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted
logic-not-delete-value: 0
logic-delete-value: 1
- 字段值为null不更新
java复制UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.set("email", null) // 明确设置为null
.eq("id", 1);
userMapper.update(null, wrapper);
9. 安全防护实践
9.1 SQL注入防护
使用QueryWrapper的安全写法:
java复制public List<User> search(String keyword) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("username", keyword); // 自动参数化
return userMapper.selectList(wrapper);
}
9.2 敏感数据脱敏
自定义TypeHandler示例:
java复制@MappedTypes(String.class)
public class SensitiveTypeHandler extends BaseTypeHandler<String> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
String parameter, JdbcType jdbcType) {
ps.setString(i, AESUtil.encrypt(parameter));
}
@Override
public String getNullableResult(ResultSet rs, String columnName) {
return AESUtil.decrypt(rs.getString(columnName));
}
}
10. 扩展功能集成
10.1 多数据源配置
动态数据源实现方案:
java复制@Configuration
@MapperScan(basePackages = "com.example.mapper")
public class DataSourceConfig {
@Bean
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DataSource dynamicDataSource() {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("master", masterDataSource());
targetDataSources.put("slave", slaveDataSource());
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(masterDataSource());
return dataSource;
}
}
10.2 分布式ID生成
集成雪花算法:
java复制@Bean
public IdentifierGenerator idGenerator() {
return entity -> SnowFlakeUtil.nextId();
}
在实际项目中,我发现合理使用MybatisPlus的Lambda表达式可以显著提高代码可读性,特别是在复杂查询场景下。对于新项目,建议从一开始就规划好自动填充字段(create_time/update_time等),这能为后期审计追溯带来很大便利。当遇到性能问题时,优先检查是否合理添加了数据库索引,MP生成的SQL可以通过配置mybatis-plus.configuration.log-impl来输出检查
