java - Spring/Hibernate 添加一个在关闭 EntityManagerFactory 之前运行的关闭钩子(Hook)

标签 java spring hibernate jakarta-ee websphere

当我关闭服务器时,我有一些工作正在填充下载和填充数据,我希望这些工作能够优雅地完成。

我尝试添加 Runtime.getRuntime().addShutDownHook() 但这似乎在 Entitymanager 已经关闭之后运行,因为在运行之前异常开始涌入。

然后我尝试添加它来实现 ServletContextListener 和

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)

它在关闭 Hook 之前运行,但仍在实体管理器关闭之后运行。

有没有办法在实体管理器关闭之前运行一些逻辑?

我正在使用

注入(inject)实体管理器
@PersistenceContext(unitName = PERSISTENCE_UNIT)
private EntityManager entityManager;

EntitymanagerFactory 是使用

创建的
@Configuration 

@Bean(name= PERSISTENCE_UNIT)
.... createEntityManagerFactory()

当实体管理器关闭时,我如何正确监听,以便我可以允许挂起的工作首先完成?

我正在 Java EE 上使用 Spring、Hibernate、JPA 和 Web 模块。

产生的异常是这样的:

java.lang.IllegalStateException: EntityManagerFactory is closed
        org.hibernate.jpa.internal.EntityManagerFactoryImpl.validateNotClosed(EntityManagerFactoryImpl.java:388)
        org.hibernate.jpa.internal.EntityManagerFactoryImpl.internalCreateEntityManager(EntityManagerFactoryImpl.java:342)
        org.hibernate.jpa.internal.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:313)
        sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        java.lang.reflect.Method.invoke(Method.java:497)
        org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:388)
        org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:541)
        com.sun.proxy.$Proxy51.createEntityManager(Unknown Source)
        org.springframework.orm.jpa.EntityManagerFactoryUtils.doGetTransactionalEntityManager(EntityManagerFactoryUtils.java:285)
        org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:252)
        com.sun.proxy.$Proxy53.getDelegate(Unknown Source)

最佳答案

这是 EntityManagerFactory当 Spring 应用程序上下文被销毁时,该 get 就会关闭。

根据您记录的异常,主运行线程已检测到应用程序销毁事件和 Spring shutdownHook将销毁事件传播到所有已注册的 bean,EntityManagerFactory包括在内。

您可能有一个批处理作业,其中有一些工作线程,它们不监听应用程序销毁事件,因此它们继续执行,因此尝试创建 EntityManager使用封闭的EntityManagerFactory .

因为应用程序上下文被破坏,不仅仅是EntityManagerFactory已关闭,但 TransactionManagerDataSource以及。这就是为什么除了放弃当前正在运行的批处理作业并简单地取消确认之外,您对此无能为力。 未完成的项目。

解决方案是使用持久消息队列来记录任何待处理的工作。如果服务器关闭,则当前处理的消息不应被确认,因此它们有机会在您下次启动服务器时重新处理。

关于java - Spring/Hibernate 添加一个在关闭 EntityManagerFactory 之前运行的关闭钩子(Hook),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28387188/

相关文章:

java - 动态 Web 应用程序 - 具有组件的平台

java - 嵌套异常是 org.hibernate.exception.SQLGrammarException : ORA-02289: sequence does not exist

java - 哪些变量在 JavaFX/Hibernate 应用程序中使用

mysql - Hibernate:如何创建两个表的关系?

java - 如何在Hibernate中映射一个合格的关联?

java - "AWT-EventQueue-0"保存 JTable (DefaultTableModel) 时出现 java.lang.NullPointerException

java - EntityManager.createNativeQuery 在使用分页时返回对象列表而不是 BigDecimal 列表

spring - 如何在 Spring 获得同一个bean的多个实例?

java - 设置ImageView相对于文本高度的宽度和高度

spring - 使用 Hibernate 使用外键 (where) 查询数据库表