ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Spring Boot 3.3与MyBatis-Plus整合开发实践

Spring Boot 3.3与MyBatis-Plus整合开发实践 1. 项目背景与技术选型最近在重构公司的一个老项目技术栈需要从传统的SSM架构升级到Spring Boot 3.3.X。考虑到MyBatis-Plus在持久层操作上的便利性决定采用这套组合方案。Spring Boot 3.3.X是2024年发布的最新稳定版本相比之前的3.2.X在性能上有显著提升特别是对GraalVM原生镜像的支持更加完善。而MyBatis-Plus 3.5.3版本已经完美适配Spring Boot 3.x系列提供了更强大的CRUD封装和动态表名支持。这个技术组合特别适合需要快速开发的中大型项目比如我们正在做的电商后台管理系统。MyBatis-Plus的Lambda表达式写法可以让代码更简洁而Spring Boot 3.3.X的新特性如虚拟线程(Virtual Threads)支持能显著提升高并发场景下的性能。实测下来同样的查询接口这套组合比原来的Spring Boot 2.7 MyBatis性能提升了约30%。2. 环境准备与项目搭建2.1 基础环境配置首先确保你的开发环境满足以下要求JDK 17Spring Boot 3.x强制要求Maven 3.6.3 或 Gradle 7.xIDE推荐IntelliJ IDEA 2023.2对Java 17新语法支持更好创建项目时可以直接使用Spring Initializr关键依赖选择Spring WebLombok简化实体类编写MySQL Driver或其他你使用的数据库驱动MyBatis-Plus注意要选兼容Spring Boot 3.x的版本pom.xml中需要显式声明MyBatis-Plus的版本号目前推荐dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.5/version /dependency2.2 数据库配置application.yml中配置数据源时需要注意几个新变化spring: datasource: url: jdbc:mysql://localhost:3306/your_db?useSSLfalseserverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 20 minimum-idle: 5Spring Boot 3.x默认使用HikariCP连接池配置项有所调整。特别提醒如果使用MySQL 8.x必须指定serverTimezone参数否则会出现时区异常。3. MyBatis-Plus核心配置3.1 基础配置类创建一个MyBatisPlusConfig配置类Configuration MapperScan(com.yourpackage.mapper) public class MyBatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 分页插件 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } Bean public ISqlInjector sqlInjector() { return new DefaultSqlInjector(); } }这里配置了两个核心插件分页插件自动处理分页逻辑支持多种数据库类型乐观锁插件通过Version注解实现乐观锁控制3.2 实体类与Mapper示例定义一个用户实体类Data TableName(sys_user) public class User { TableId(type IdType.AUTO) private Long id; private String username; private String password; TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; Version private Integer version; }对应的Mapper接口public interface UserMapper extends BaseMapperUser { // 自定义复杂查询方法 Select(SELECT * FROM sys_user WHERE username LIKE CONCAT(%,#{username},%)) ListUser selectByUsernameLike(Param(username) String username); }BaseMapper已经提供了基本的CRUD方法自定义方法可以通过注解或XML方式实现。注意Spring Boot 3.x对Java 17的记录类(Record)支持更好但MyBatis-Plus目前对Record的支持还不完善建议仍使用传统的POJO类。4. 高级特性与最佳实践4.1 动态表名处理在分表场景下动态表名是非常实用的功能。我们可以实现DynamicTableNameInnerInterceptorpublic class MyDynamicTableNameHandler implements TableNameHandler { Override public String dynamicTableName(String sql, String tableName) { // 根据业务逻辑返回实际表名 if (sys_user.equals(tableName)) { return sys_user_ LocalDate.now().getYear(); } return tableName; } } // 在配置类中添加 interceptor.addInnerInterceptor(new DynamicTableNameInnerInterceptor(new MyDynamicTableNameHandler()));4.2 多租户实现对于SaaS应用多租户是常见需求。MyBatis-Plus提供了TenantLineInnerInterceptorpublic class MyTenantLineHandler implements TenantLineHandler { Override public String getTenantIdColumn() { return tenant_id; } Override public Expression getTenantId() { // 从上下文中获取当前租户ID return new LongValue(1L); } Override public boolean ignoreTable(String tableName) { // 不需要过滤的表 return !Arrays.asList(sys_user, sys_role).contains(tableName); } } // 配置中添加 interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new MyTenantLineHandler()));4.3 性能优化建议批量操作使用executeBatch提升批量插入/更新性能ListUser userList ...; userService.saveBatch(userList, 1000); // 每1000条提交一次Lambda查询比字符串更安全高效ListUser users userMapper.selectList( Wrappers.UserlambdaQuery() .eq(User::getUsername, admin) .between(User::getCreateTime, startDate, endDate) );二级缓存对于读多写少的场景可以启用cache typeorg.mybatis.caches.ehcache.EhcacheCache/5. 常见问题排查5.1 类型转换异常Spring Boot 3.x对Java 8日期时间类型的处理更严格。如果遇到LocalDateTime转换问题可以添加以下配置spring: mvc: format: date-time: yyyy-MM-dd HH:mm:ss5.2 分页不生效确保配置了分页插件方法返回类型是IPage参数中传入Page对象// 正确用法 IPageUser page userMapper.selectPage(new Page(1, 10), queryWrapper);5.3 自动填充失效检查实体类字段有TableField(fill FieldFill.xxx)注解实现了MetaObjectHandlerComponent 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()); } }5.4 事务不回滚Spring Boot 3.x默认代理方式可能有变化确保方法有Transactional注解异常是RuntimeException或Error同一个类内部调用不会触发事务可以在配置中添加spring: aop: proxy-target-class: true6. 测试与验证6.1 单元测试配置测试类需要添加注解SpringBootTest Transactional Rollback public class UserMapperTest { Autowired private UserMapper userMapper; Test public void testInsert() { User user new User(); user.setUsername(test); int result userMapper.insert(user); assertEquals(1, result); } }6.2 接口测试建议使用Testcontainers进行集成测试更接近真实环境Testcontainers SpringBootTest public class UserServiceIT { Container static MySQLContainer? mysql new MySQLContainer(mysql:8.0); DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { registry.add(spring.datasource.url, mysql::getJdbcUrl); registry.add(spring.datasource.username, mysql::getUsername); registry.add(spring.datasource.password, mysql::getPassword); } // 测试方法... }7. 部署注意事项7.1 原生镜像构建Spring Boot 3.3对GraalVM支持更好构建原生镜像时需要处理MyBatis-Plus的动态代理./mvnw -Pnative native:compile需要在reflect-config.json中添加{ name: com.baomidou.mybatisplus.core.metadata.TableInfoHelper, methods: [{name: init, parameterTypes: [] }] }7.2 生产环境配置建议的application-prod.yml配置mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl cache-enabled: true global-config: db-config: logic-delete-field: deleted # 逻辑删除字段 logic-not-delete-value: 0 logic-delete-value: 18. 性能监控集成Micrometer监控SQL性能Bean public MybatisPlusInterceptor performanceInterceptor() { PerformanceInterceptor interceptor new PerformanceInterceptor(); interceptor.setMaxTime(1000); // SQL执行最大时长超过自动打印日志 interceptor.setFormat(true); // 格式化SQL return interceptor; }结合Prometheus和Grafana可以可视化监控SQL执行情况。
返回列表