Spring/Hibernate 添加一个在关闭 EntityManagerFactory 之前运行的关闭钩子

2023-12-25

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

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

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

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent)

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

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

我正在使用注入实体管理器

@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 就会关闭。

根据您记录的异常,主运行线程已检测到应用程序销毁事件并且弹簧关闭钩子 http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/AbstractApplicationContext.html#registerShutdownHook--将 destroy 事件传播到所有已注册的 bean,EntityManagerFactory包括。

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring/Hibernate 添加一个在关闭 EntityManagerFactory 之前运行的关闭钩子 的相关文章

随机推荐