调用存储过程时出现Connection is closed错误的技术求助
问题分析与解决方案
核心问题
- 直接创建并持有
EntityManager实例,未通过Spring容器管理其生命周期,导致长期持有的连接被数据库或连接池回收后,再次调用存储过程时触发连接关闭错误。 - HikariCP配置缺少连接有效性校验参数,无法自动剔除池中失效的连接。
具体修复步骤
1. 修正EntityManager的管理方式
不要手动创建并返回EntityManager实例,改为让Spring管理EntityManagerFactory,并通过注解注入EntityManager来自动管控生命周期:
修改原配置中的msEntityManagerFactory方法,直接返回EntityManagerFactory:
@Bean public EntityManagerFactory msEntityManagerFactory(@Qualifier("msDataSource") DataSource msDataSource) { LocalContainerEntityManagerFactoryBean emFactory = new LocalContainerEntityManagerFactoryBean(); emFactory.setDataSource(msDataSource); emFactory.setPackagesToScan(new String[]{this.packageScanDir}); HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setDatabasePlatform("org.hibernate.dialect.SQLServer2012Dialect"); emFactory.setJpaVendorAdapter(adapter); emFactory.setPersistenceUnitName(this.entityManagerName); emFactory.setPersistenceProviderClass(HibernatePersistenceProvider.class); emFactory.afterPropertiesSet(); return emFactory.getObject(); }
在业务代码中通过注解注入EntityManager,Spring会自动处理连接的获取与释放:
@Service public class YourBizService { @PersistenceContext(unitName = "你的entityManagerName") private EntityManager entityManager; public void callStoredProcedure() { StoredProcedureQuery query = entityManager.createStoredProcedureQuery("你的存储过程名称"); // 设置存储过程参数、执行逻辑 query.execute(); } }
2. 完善HikariCP连接池有效性配置
添加连接校验、超时相关参数,让连接池自动剔除失效连接:
public DataSource msDataSource() { HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setDriverClassName(this.driveClassName); hikariConfig.setJdbcUrl(this.url); hikariConfig.setUsername(this.username); hikariConfig.setPassword(this.password); hikariConfig.setMaximumPoolSize(this.maxActive); hikariConfig.setMinimumIdle(this.minIdle); hikariConfig.setConnectionTimeout((long)this.maxWait); hikariConfig.setPoolName(this.entityManagerName); // 新增连接有效性校验配置 hikariConfig.setConnectionTestQuery("SELECT 1"); // SQLServer连接校验语句 hikariConfig.setMaxLifetime(1740000); // 29分钟,需小于数据库端连接超时时间 hikariConfig.setIdleTimeout(600000); // 10分钟,空闲连接超时回收 hikariConfig.setValidationTimeout(5000); // 连接校验超时时间 return new HikariDataSource(hikariConfig); }
3. 手动管理EntityManager的资源释放(不推荐,仅作应急方案)
如果必须手动创建EntityManager,务必在使用完成后关闭:
EntityManager em = msEntityManagerFactory.createEntityManager(); try { // 存储过程调用逻辑 } finally { if (em.isOpen()) { em.close(); } }
内容的提问来源于stack exchange,提问作者user3763183
相关产品推荐
相关产品推荐

