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

使用SharedEntityManagerCreator创建EntityManager引发资源泄漏的解决方法

问题:手动创建EntityManager导致资源泄漏的解决方案选择

未使用@PersistenceContext注解,而是手动通过如下方式创建EntityManager实例:

private static final EntityManagerFactory entityManagerFactory = (EntityManagerFactory) ApplicationContextHolder.getContext().getBean("projEntityManagerFactory");
    
private Boolean update(String par) {
    EntityManager entityManager = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
    
    StoredProcedureQuery query = entityManager.createStoredProcedureQuery(Constants.UPDATE_PROCEDURE);
    
    //other update query builder code
    
    return (Boolean) query.getOutputParameterValue(4);
}

目前出现资源泄漏相关警告,推测是因为EntityManager使用后未关闭。尝试了两种方案:1. 在方法上添加@Transactional注解,使查询绑定事务,事务结束时自动关闭资源;2. 参考文档建议使用EntityTransaction并调用entityManager.close()关闭连接。请问哪种方案正确?如何解决该资源泄漏警告?


解决方案分析

方案1:使用@Transactional注解

该方案可行,且更符合Spring生态规范,前提是你的类需被Spring容器管理(即标注@Component/@Service等注解成为Bean)。

当方法被@Transactional修饰时,Spring会自动完成以下操作:

  • 事务启动时,将EntityManager绑定到当前线程上下文
  • 事务结束(提交/回滚)后,自动关闭EntityManager并释放资源
  • 结合SharedEntityManagerCreator创建的共享EntityManager,Spring会复用事务上下文内的实例,避免重复创建资源

只需给update方法添加注解即可:

@Transactional
private Boolean update(String par) {
    EntityManager entityManager = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
    
    StoredProcedureQuery query = entityManager.createStoredProcedureQuery(Constants.UPDATE_PROCEDURE);
    
    //other update query builder code
    
    return (Boolean) query.getOutputParameterValue(4);
}

方案2:手动管理EntityTransaction并关闭EntityManager

该方案也能解决资源泄漏,但需要严格的手动资源管理,必须确保entityManager.close()在任何情况下都能执行,否则仍会出现泄漏。需用try-finally块包裹逻辑:

private Boolean update(String par) {
    EntityManager entityManager = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory);
    EntityTransaction tx = null;
    try {
        tx = entityManager.getTransaction();
        tx.begin();
        
        StoredProcedureQuery query = entityManager.createStoredProcedureQuery(Constants.UPDATE_PROCEDURE);
        //other update query builder code
        
        Boolean result = (Boolean) query.getOutputParameterValue(4);
        tx.commit();
        return result;
    } catch (Exception e) {
        if (tx != null && tx.isActive()) {
            tx.rollback();
        }
        throw e; // 或根据业务需求处理异常
    } finally {
        if (entityManager.isOpen()) {
            entityManager.close();
        }
    }
}

这种方式适合不受Spring事务管理的场景,但手动编码容易遗漏异常处理或资源关闭步骤,出错概率较高。


推荐方案

优先选择方案1,Spring的事务管理已封装了资源生命周期、事务提交回滚等逻辑,无需手动编写冗余代码,能有效避免资源泄漏,同时更贴合Spring开发的最佳实践。

内容的提问来源于stack exchange,提问作者user-newhc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:23:20