You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot测试中EntityManagerFactory关闭缓慢问题求助

Spring Boot测试中EntityManagerFactory关闭延迟问题的解决方案

我的Spring Boot v3.2.0应用基于JDK 21,测试套件执行完毕后,关闭创建的EntityManagerFactory Bean耗时超30秒,占总测试时长的33%。日志显示有3个该Bean关闭需11秒,主要耗时在等待关联的Hikari连接池关闭。应用自身关闭时无此延迟,推测是因为应用仅创建1个该Bean实例,而测试套件因构建不同应用上下文创建了14个。现寻求两种方向的解决办法:

  • 减少测试中EntityManagerFactory Bean的创建数量
  • 缩短单个EntityManagerFactory Bean的关闭时间

当前Hikari配置

spring.datasource.hikari.maximumPoolSize=2

测试套件相关日志

2023-12-07T15:53:41.555Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:53:41.556Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2023-12-07T15:53:41.557Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2023-12-07T15:53:52.831Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:53:52.832Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Shutdown initiated...
2023-12-07T15:53:52.834Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Shutdown completed.
2023-12-07T15:54:03.861Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:03.863Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Shutdown initiated...
2023-12-07T15:54:03.865Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Shutdown completed.
2023-12-07T15:54:03.886Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:03.887Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-4 - Shutdown initiated...
2023-12-07T15:54:03.888Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-4 - Shutdown completed.
2023-12-07T15:54:03.899Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:03.899Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-5 - Shutdown initiated...
2023-12-07T15:54:03.900Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-5 - Shutdown completed.
2023-12-07T15:54:14.916Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.917Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-6 - Shutdown initiated...
2023-12-07T15:54:14.919Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-6 - Shutdown completed.
2023-12-07T15:54:14.938Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.939Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-7 - Shutdown initiated...
2023-12-07T15:54:14.940Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-7 - Shutdown completed.
2023-12-07T15:54:14.953Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.954Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-8 - Shutdown initiated...
2023-12-07T15:54:14.954Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-8 - Shutdown completed.
2023-12-07T15:54:14.955Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.955Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-9 - Shutdown initiated...
2023-12-07T15:54:14.956Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-9 - Shutdown completed.
2023-12-07T15:54:14.960Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.960Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-10 - Shutdown initiated...
2023-12-07T15:54:14.960Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-10 - Shutdown completed.
2023-12-07T15:54:14.964Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.964Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-11 - Shutdown initiated...
2023-12-07T15:54:14.965Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-11 - Shutdown completed.
2023-12-07T15:54:14.968Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.968Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-12 - Shutdown initiated...
2023-12-07T15:54:14.969Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-12 - Shutdown completed.
2023-12-07T15:54:14.972Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.972Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-13 - Shutdown initiated...
2023-12-07T15:54:14.972Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-13 - Shutdown completed.
2023-12-07T15:54:14.975Z --- j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2023-12-07T15:54:14.976Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-14 - Shutdown initiated...
2023-12-07T15:54:14.992Z --- com.zaxxer.hikari.HikariDataSource       : HikariPool-14 - Shutdown completed.

> Task :test

SUCCESS: Executed 706 tests in 1m 37s (2 skipped)

解决方案

一、减少测试中EntityManagerFactory的创建次数

  1. 复用Spring应用上下文

    • 尽量让测试类使用相同的配置注解组合,比如都用@SpringBootTest且未指定不同的配置类或属性,Spring会自动缓存上下文,无需每次重建。
    • 避免滥用@DirtiesContext注解,只有当必须重置上下文时才使用,否则会强制销毁当前上下文并重建,增加创建次数。
    • 将共享的测试配置提取到父类测试中,子类测试继承父类,确保上下文复用。
  2. 使用轻量测试切片

    • 针对不需要完整Spring上下文的测试,使用测试切片注解,比如@DataJpaTest、@RepositoryTest等。这些切片会创建更轻量的上下文,仅加载必要的Bean,减少EntityManagerFactory的创建次数。
    • 尽量保持切片配置一致,不同配置的切片仍会触发上下文重建。

二、加快单个EntityManagerFactory的关闭速度

  1. 调优Hikari连接池关闭参数

    • 设置spring.datasource.hikari.shutdownTimeout参数,缩短连接池关闭的等待时间,例如设置为5秒:
      spring.datasource.hikari.shutdownTimeout=5000
      
    • 测试结束前确保所有EntityManager都被正确关闭,避免连接池因等待未归还的连接而超时。可以在@AfterEach方法中手动关闭EntityManager,或使用@Transactional注解让Spring自动管理事务和连接。
  2. 优化JPA关闭相关配置

    • 开启spring.jpa.close-on-exit=true,确保JPA在关闭时主动清理资源。
    • 检查测试中是否存在延迟加载的实体导致关闭时仍有未完成的数据库操作,确保所有数据操作都在事务内完成并提交或回滚。
  3. 排查连接泄漏

    • 启用Hikari的连接泄漏检测:设置spring.datasource.hikari.leakDetectionThreshold=2000,日志会输出泄漏连接的栈信息,帮助定位未释放的连接。
    • 确保测试中使用的数据库连接都被正确归还,例如测试方法结束时关闭EntityManager,或通过事务注解自动管理连接生命周期。

内容的提问来源于stack exchange,提问作者Dónal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 15:37:33