Spring Boot WebSocket应用出现JDBC连接池耗尽无法获取连接问题求助
问题分析与解决方案
从你的错误信息HikariPool-1 - Connection is not available, request timed out来看,核心问题是数据库连接池被耗尽了,根源出在你的EntityManager和事务管理代码上,结合细节给你拆解一下:
1. 为什么会耗尽连接?
你手动创建了EntityManager但没有正确关闭它:
EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); // ... 业务代码 entityManager.getTransaction().commit(); // 这里没有关闭EntityManager!
每次执行这段代码,都会从连接池获取一个连接,但使用后没有释放,日积月累连接池就被占满,新请求拿不到连接就超时了。
另外你还混用了Spring Data JPA的entityRepository.save()和手动的EntityManager事务——Spring Data JPA的Repository方法本身已经由Spring管理事务和连接,手动开事务再调用save,会导致连接资源的重复占用和释放异常。
2. 修复方案
方案一:完全使用Spring Data JPA的自动事务管理(推荐)
删掉手动的EntityManager代码,让Spring帮你管理事务和连接,这是Spring Boot的最佳实践:
// 确保你的Service类上加上@Transactional注解 @Service @Transactional public class YourService { private final EntityRepository entityRepository; // 构造注入 public YourService(EntityRepository entityRepository) { this.entityRepository = entityRepository; } public void updateEntity(Object object) { // 先查询出实体(假设你有id参数) Entity entity = entityRepository.findById(object.getString("id")) .orElseThrow(() -> new RuntimeException("Entity not found")); entity.setName(object.getString("name")); // 直接save,Spring会自动处理事务和连接 entityRepository.save(entity); } }
这样Spring会自动帮你处理连接的获取与释放,不会出现连接泄漏。
方案二:如果必须手动使用EntityManager
一定要用try-with-resources语法确保EntityManager被关闭,或者在finally块里手动关闭:
// try-with-resources会自动关闭EntityManager try (EntityManager entityManager = entityManagerFactory.createEntityManager()) { entityManager.getTransaction().begin(); entity.setName(object.getString("name")); // 这里不要用repository.save,改用EntityManager的merge方法 entityManager.merge(entity); entityManager.flush(); entityManager.getTransaction().commit(); } catch (Exception e) { // 异常时回滚事务 if (entityManager != null && entityManager.getTransaction().isActive()) { entityManager.getTransaction().rollback(); } throw e; }
方案三:调整连接池配置(辅助优化)
如果你的业务确实需要更多连接,可以在application.properties或application.yml里调整HikariCP的参数:
# 最大连接数,根据数据库配置和业务调整,默认是10 spring.datasource.hikari.maximum-pool-size=20 # 连接超时时间,默认30秒,可适当缩短 spring.datasource.hikari.connection-timeout=10000 # 空闲连接超时时间,自动释放闲置连接 spring.datasource.hikari.idle-timeout=600000
3. 额外注意点
- 不要混用手动事务和Spring的声明式事务,避免资源管理混乱;
- Spring Boot的
spring-boot-starter-data-jpa已经默认集成了HikariCP,无需额外配置连接池,但可根据业务调整参数; - 你的Gradle配置里用了Spring Boot 2.2.0的快照版,建议换成同系列的稳定RELEASE版本,避免潜在的未知bug。
内容的提问来源于stack exchange,提问作者Sixiy2616
相关产品推荐
相关产品推荐

