当我关闭服务器时,我有一些工作正在填充下载和填充数据,我希望这些工作能够优雅地完成。
我尝试添加 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
已关闭,但 TransactionManager
和 DataSource
以及。这就是为什么除了放弃当前正在运行的批处理作业并简单地取消确认之外,您对此无能为力。
未完成的项目。
解决方案是使用持久消息队列来记录任何待处理的工作。如果服务器关闭,则当前处理的消息不应被确认,因此它们有机会在您下次启动服务器时重新处理。
关于java - Spring/Hibernate 添加一个在关闭 EntityManagerFactory 之前运行的关闭钩子(Hook),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28387188/