SpringBoot+MyBatis+MySQL企业级开发实战指南

1. 项目概述与环境准备

在Java企业级开发领域,SpringBoot+MyBatis+MySQL的技术组合已成为中小型项目的黄金搭档。作为从业多年的全栈开发者,我见证过太多团队在项目初始化阶段就埋下技术债。本文将分享如何用IntelliJ IDEA从零搭建一个结构清晰、可维护性高的标准工程,重点解决三个核心问题:依赖管理的版本控制、MyBatis与SpringBoot的优雅集成、以及开发环境与生产环境的数据库配置分离。

1.1 工具选型与版本控制

工欲善其事必先利其器,以下是经过生产验证的工具组合:

  • IDEA 2023.3+(社区版足够,无需破解)
  • Java 17(LTS版本,新项目不建议再用Java 8)
  • SpringBoot 3.1.5(注意GroupId已改为org.springframework.boot)
  • MyBatis 3.5.13+ MyBatis-Spring 3.0.2
  • MySQL 8.0.33(生产环境推荐Percona分支)

重要提示:版本兼容性直接影响后续开发体验。SpringBoot 3.x要求JDK 17+,若必须使用JDK 8,需降级到SpringBoot 2.7.x系列。

1.2 初始化工程的正确姿势

通过IDEA创建项目时,90%的开发者会忽略这两个关键配置:

  1. Artifact命名:建议采用反向域名+功能描述(如com.example.warehouse)
  2. 包结构规划:提前划分好controller/service/dao分层,避免后期重构

实操步骤:

# 使用Spring Initializr生成项目骨架 curl https://start.spring.io/starter.zip \ -d type=gradle-project \ -d language=java \ -d packaging=jar \ -d javaVersion=17 \ -d groupId=com.example \ -d artifactId=demo \ -d name=demo \ -d dependencies=web,mysql,mybatis \ -o demo.zip

2. 核心组件集成实战

2.1 MyBatis的三层集成方案

数据源配置(application.yml示例)
spring: datasource: url: jdbc:mysql://localhost:3306/demo?useSSL=false&serverTimezone=Asia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 15 # 根据CPU核心数调整 connection-timeout: 30000 mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true # 自动驼峰转换
注解式Mapper的最佳实践
@Mapper public interface UserMapper { @Select("SELECT * FROM users WHERE id = #{id}") User findById(@Param("id") Long id); @Options(useGeneratedKeys = true, keyProperty = "id") @Insert("INSERT INTO users(name) VALUES(#{name})") int insert(User user); }

2.2 事务管理的坑与解决方案

SpringBoot默认事务管理经常遇到的三个坑:

  1. 自调用失效问题:同类方法调用不会触发事务代理
  2. 异常捕获陷阱:try-catch会"吃掉"异常导致事务不回滚
  3. 连接泄漏风险:MyBatis查询未关闭ResultSet

解决方案示例:

@Service @Transactional(rollbackFor = Exception.class) // 明确指定回滚异常类型 public class UserService { private final UserMapper userMapper; // 构造器注入代替@Autowired public UserService(UserMapper userMapper) { this.userMapper = userMapper; } public void createUser(User user) { userMapper.insert(user); // 模拟业务异常 if (user.getName().contains("test")) { throw new RuntimeException("Invalid username"); } } }

3. 工程化进阶技巧

3.1 多环境配置方案

采用profile区分环境是基础操作,但真正的工程化需要更多考量:

# application-dev.yml spring: datasource: url: jdbc:mysql://localhost:3306/dev_db username: dev_user # application-prod.yml spring: datasource: url: jdbc:mysql://prod-db.cluster:3306/prod_db?useSSL=true username: ${DB_USER} password: ${DB_PASSWORD} # 从环境变量读取

启动时通过VM参数指定环境:

-Dspring.profiles.active=prod

3.2 监控与健康检查

生产环境必备的监控端点配置:

management: endpoints: web: exposure: include: health,info,metrics endpoint: health: show-details: always metrics: enabled: true

自定义健康检查指标示例:

@Component public class DatabaseHealthIndicator implements HealthIndicator { private final DataSource dataSource; public DatabaseHealthIndicator(DataSource dataSource) { this.dataSource = dataSource; } @Override public Health health() { try (Connection conn = dataSource.getConnection()) { return Health.up().withDetail("version", conn.getMetaData().getDatabaseProductVersion()).build(); } catch (Exception e) { return Health.down(e).build(); } } }

4. 性能优化实战

4.1 MyBatis二级缓存陷阱

虽然MyBatis支持二级缓存,但在分布式环境中直接使用会导致严重的数据一致性问题。推荐方案:

@Configuration public class MyBatisConfig { @Bean public MyBatisSqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception { MyBatisSqlSessionFactoryBean factory = new MyBatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); // 显式关闭二级缓存 org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration(); config.setCacheEnabled(false); factory.setConfiguration(config); return factory; } }

4.2 连接池参数调优

HikariCP推荐配置(针对4核8G服务器):

spring: datasource: hikari: minimum-idle: 5 maximum-pool-size: 20 idle-timeout: 30000 max-lifetime: 1800000 connection-timeout: 30000 connection-test-query: SELECT 1

5. 开发效率提升技巧

5.1 MyBatisX插件妙用

IDEA安装MyBatisX插件后可以实现:

  • XML与Mapper接口方法智能跳转
  • SQL语句自动补全
  • 一键生成CRUD代码

5.2 测试数据准备

使用Testcontainers实现集成测试自动化:

@Testcontainers @SpringBootTest class UserRepositoryTest { @Container static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0"); @DynamicPropertySource static void registerPgProperties(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", mysql::getJdbcUrl); registry.add("spring.datasource.username", mysql::getUsername); registry.add("spring.datasource.password", mysql::getPassword); } @Test void testSaveUser() { // 测试逻辑 } }

6. 常见问题排查指南

6.1 连接池耗尽问题

现象:出现"HikariPool-1 - Connection is not available"错误

排查步骤:

  1. 检查active连接数:management.endpoints.web.exposure.include=metrics
  2. 分析慢查询:spring.datasource.hikari.leak-detection-threshold=60000
  3. 检查事务未关闭情况

6.2 MyBatis映射失败

典型错误:"Invalid bound statement (not found)"

解决方案检查清单:

  1. 确认mapper.xml文件在resources/mapper目录下
  2. 检查namespace与Mapper接口全限定名一致
  3. 方法名与statement id完全匹配
  4. 清理编译输出重新构建

7. 项目结构优化建议

标准项目目录结构示例:

src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ ├── config/ # 配置类 │ │ ├── controller/ # 表现层 │ │ ├── service/ # 业务逻辑 │ │ ├── dao/ # 数据访问 │ │ ├── model/ # 数据实体 │ │ └── DemoApplication.java │ └── resources/ │ ├── mapper/ # MyBatis映射文件 │ ├── static/ # 静态资源 │ ├── templates/ # 模板文件 │ ├── application.yml # 主配置 │ └── application-dev.yml # 环境配置 └── test/ # 测试代码

8. 安全防护要点

8.1 SQL注入防护

即使使用MyBatis也需要注意:

  • 禁止拼接SQL:"SELECT * FROM user WHERE id = " + id
  • 动态表名使用${}时要白名单校验
  • 复杂查询使用Provider类:
@SelectProvider(type = UserSqlProvider.class, method = "findByCondition") List<User> findByCondition(@Param("condition") UserCondition condition); public class UserSqlProvider { public String findByCondition(UserCondition condition) { return new SQL() {{ SELECT("*"); FROM("users"); if (condition.getName() != null) { WHERE("name = #{condition.name}"); } }}.toString(); } }

8.2 敏感数据加密

数据库层面加密方案:

spring: datasource: password: jdbc:mysql://...?passwordEncryptor=type:AES;key:${ENCRYPT_KEY}

或者在应用层使用Jasypt:

@Bean public StringEncryptor encryptor() { PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPassword(System.getenv("ENCRYPT_PASSWORD")); return encryptor; }

9. 部署与监控

9.1 打包注意事项

生产环境打包建议:

# 跳过测试构建 ./gradlew clean build -x test # 分离依赖jar减少体积 jar { enabled = true archiveClassifier = '' } bootJar { archiveClassifier = 'boot' }

9.2 健康检查端点

Kubernetes就绪探针配置示例:

spring: application: name: user-service management: endpoint: health: probes: enabled: true health: livenessstate: enabled: true readinessstate: enabled: true

10. 升级与迁移策略

10.1 SpringBoot 2.x → 3.x

关键变更点:

  1. Jakarta EE 9+(javax包名改为jakarta)
  2. Hibernate 6.x新特性
  3. 移除SpringFox支持,改用SpringDoc OpenAPI

10.2 MySQL 5.7 → 8.0

注意事项:

  1. 默认认证插件改为caching_sha2_password
  2. 需要更新连接器版本:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>

11. 扩展技术选型

11.1 MyBatis-Plus进阶

增强功能示例:

@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { public Page<User> queryByPage(PageParam param) { return lambdaQuery() .like(StringUtils.isNotBlank(param.getKeyword()), User::getName, param.getKeyword()) .page(new Page<>(param.getPage(), param.getSize())); } }

11.2 多数据源方案

动态数据源配置要点:

@Configuration @MapperScan(basePackages = "com.example.dao.db1", sqlSessionTemplateRef = "db1SqlSessionTemplate") public class Db1Config { @Bean @ConfigurationProperties("spring.datasource.db1") public DataSource db1DataSource() { return DataSourceBuilder.create().build(); } @Bean public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources("classpath:mapper/db1/*.xml")); return bean.getObject(); } }

12. 性能监控方案

12.1 Micrometer指标

集成Prometheus监控:

management: metrics: export: prometheus: enabled: true endpoint: prometheus: enabled: true

自定义业务指标:

@RestController public class OrderController { private final Counter orderCounter; public OrderController(MeterRegistry registry) { this.orderCounter = registry.counter("orders.created"); } @PostMapping("/orders") public Order createOrder() { orderCounter.increment(); // 业务逻辑 } }

13. 缓存集成策略

13.1 Redis二级缓存

替代MyBatis原生二级缓存:

@Configuration @EnableCaching public class CacheConfig { @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { return RedisCacheManager.builder(factory) .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofMinutes(30)) .disableCachingNullValues()) .build(); } } @Cacheable(value = "users", key = "#id") public User getUser(Long id) { return userMapper.selectById(id); }

14. 日志收集方案

14.1 ELK集成

Logback配置示例:

<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>logstash:5044</destination> <encoder class="net.logstash.logback.encoder.LogstashEncoder"> <customFields>{"app":"${spring.application.name}"}</customFields> </encoder> </appender>

15. 容器化部署

15.1 Dockerfile优化

分层构建示例:

# 构建阶段 FROM gradle:7-jdk17 AS builder WORKDIR /app COPY build.gradle . COPY src ./src RUN gradle build -x test # 运行阶段 FROM eclipse-temurin:17-jre WORKDIR /app COPY --from=builder /app/build/libs/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java","-jar","app.jar"]

16. 持续集成方案

16.1 GitHub Actions

自动化测试流水线:

name: CI on: [push] jobs: build: runs-on: ubuntu-latest services: mysql: image: mysql:8.0 env: MYSQL_ROOT_PASSWORD: root ports: - 3306:3306 steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: distribution: 'temurin' java-version: '17' - run: ./gradlew build

17. 代码质量保障

17.1 SonarQube集成

Gradle配置示例:

plugins { id "org.sonarqube" version "3.5.0.2730" } sonarqube { properties { property "sonar.host.url", "http://localhost:9000" property "sonar.login", System.getenv("SONAR_TOKEN") } }

18. API文档生成

18.1 SpringDoc OpenAPI

配置示例:

@OpenAPIDefinition( info = @Info(title = "用户服务API", version = "1.0") ) public class OpenApiConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .components(new Components()) .info(new Info().title("用户服务API").version("1.0")); } }

访问地址:http://localhost:8080/swagger-ui.html

19. 压力测试方案

19.1 JMeter测试计划

关键测试指标:

  • 吞吐量(Requests/sec)
  • 95%响应时间
  • 错误率
  • 数据库连接池使用率

测试脚本保存为src/test/resources/jmeter/UserTest.jmx

20. 项目总结与演进

经过完整项目实践后,建议从三个维度持续优化:

  1. 工程规范:引入Checkstyle/Spotless统一代码风格
  2. 架构演进:随着业务复杂度的提升,考虑引入DDD分层
  3. 性能优化:建立基准测试体系,量化性能指标

技术栈的升级路线建议:

  • 初期:SpringBoot + MyBatis(快速迭代)
  • 中期:引入Spring Cloud组件(服务治理)
  • 后期:考虑Kotlin协程/Quarkus等新技术方案