当前位置: 首页 > 知识库问答 >
问题:

Spring Boot在关机时关闭Hibernate会话--在@Async方法完成之前

韦飞尘
2023-03-14

排定的方法保留有限数量的作业,并调用执行实际工作的xyjobprocessor上的@async方法。

@Component
public class XYJobProcessingTimer {

    private final XYJobService      xyJobService;
    private final XYJobProcessor    xyJobProcessor;

    //constructor skipped

    @Scheduled(initialDelayString = "${initial_delay}", fixedDelayString = "${delay}")
    public void performXYJobProcessing() {
        final String ticket = UUID.randomUUID().toString();
        final int reservedJobs = xyJobService.findAndReserveReadyXYJobs(ticket);

        if (reservedJobs > 0) {
            final Collection<XYJob> xyJobs = xyJobService.readReservedJobs(ticket);
            xyJobProcessor.process(xyJobs);
        }
    }

}

异步处理机

@Async带注释的方法调用访问EntityManager的服务。

@Service
public class XYJobProcessor {

    private final XYJobService  xyJobService;

    // constructor skipped

    @Async("xyJobProcessorExecutor")
    public void process(final Collection<XYJob> jobs) {
        // This service uses the EntityManager and takes some time depending o job count.
        xyJobService.createXYJobsAndDelete(jobs);
    }

}
@Configuration
public class AsyncExecutorConfiguration {

    @Bean(name = "xyJobProcessorExecutor")
    public Executor xyJobProcessorExecutor() {
        final SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
        executor.setConcurrencyLimit(10);
        executor.setThreadNamePrefix("Hasselhoff-");
        return executor;
    }

}
2017-08-31 16:10:54.212 ERROR 12663 --- [Hasselhoff-12] .a.i.SimpleAsyncUncaughtExceptionHandler : Unexpected error occurred invoking async method 'public void de.xy.services.XYJobProcessor.process(java.util.Collection)'.org.springframework.orm.jpa.JpaSystemException: Session is closed!; nested exception is org.hibernate.SessionException: Session is closed!
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333)
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
        at de.xy.services.XYJobService$$EnhancerBySpringCGLIB$$6b9cb1ae.createXYJobsAndDelete(<generated>)
        at de.xy.services.XYJobProcessor.process(XYJobProcessor.java:24)
        at de.xy.services.XYJobProcessor$$FastClassBySpringCGLIB$$ccc40c8f.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:115)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at org.springframework.core.task.SimpleAsyncTaskExecutor$ConcurrencyThrottlingRunnable.run(SimpleAsyncTaskExecutor.java:268)
        at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.SessionException: Session is closed!
        at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:132)
        at org.hibernate.internal.SessionImpl.getPersistenceContext(SessionImpl.java:2088)
        at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:340)
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
        at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
        at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
        at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
        at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
        at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)
        at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
        ... 17 common frames omitted

共有1个答案

赏梓
2023-03-14

感谢@M.deinum,我发现了如何避免问题:

使用ThreadPoolTaskExecutor(而不是SimpleAsynctAskExecutor)并将其AwaitTerminationSeconds属性与WaitFortaskStoCompleteOnShutdown设置为True结合使用,可以解决我的问题。

setAwaitTerminationSeconds的JavaDoc中:

 类似资料:
  • 大家好,正在使用Spring+JPA/Hibernate+Maven并尝试从DB获取记录。所以当我朗姆酒时,我的应用程序会出现如下错误 这是一段代码

  • 问题内容: 背景 我正在客户端使用HTTP流(服务器推送)情况下的响应。尽管服务器可以通过关闭响应来关闭连接,但是客户端也需要这样做。 问题 客户端在一个单独的线程中处理,如下所示: 因此,当我从发起连接的线程进行调用时(重要的信息是它与处理输入的线程不同),该调用将无限期挂起。我什至把它留了一夜,它仍然挂着。即使打电话也无济于事。 有什么建议吗? 问题答案: 在没有可用字节的情况下,如果不更改读

  • 问题内容: 我创建了一个基于会话的简单登录页面。 并添加了一个包含此内容的注销页面 现在,当我关闭浏览器/页面并重新打开它时,会话的值仍然存在。 我想知道如何完全销毁页面/浏览器关闭上的会话。 问题答案: 如果您使用: 关闭浏览器时,您的会话cookie将会被破坏…因此,在关闭浏览器之前,您的会话将是良好的。IE浏览器 您登录并登录,然后关闭浏览器,然后重新打开,再次进入该站点,您将不会登录。

  • 问题内容: 我最近开始在应用程序中使用hibernate和c3p0作为ORM。但是,当我关闭会话工厂时,连接池不会自行关闭!这是我的应用程序中 唯一 可以进行会话操作的地方。 这是我的配置文件 请注意,空闲连接非常短的原因是它是我尚未通过集成测试的唯一方法。他们经常打开和关闭会话工厂,因此我总是用尽所有连接。正如我们在项目开始时一样,从长远来看,我认为这不是一个非常可持续的策略。 需要注意的“有趣

  • 问题内容: 与此问题相关(答案并没有真正指向重点): 使用Struts2hibernate-使用完整的hibernate插件或其他方法关闭会话? 我有相同的设置:Struts 2.2.3和struts2-fullhibernatecore-plugin-2.2.2-GA。我没有为Struts2和插件更改任何默认设置。我正在使用MySQL,没有其他连接池,也没有任何花哨的地方。 我在动作中使用以下代

  • 问题内容: 我是hibernate的新手,在阅读了hibernateapi和教程之后,似乎该会话在不使用时应关闭。 像这样: 在独立应用程序中使用它时,我没有问题。但是我不确定在Web应用程序中使用时。 例如,我有一个servlet:从客户端接收参数,然后调用Manager来根据参数查询内容,如下所示: 我应该使用查询方法关闭会话吗? 由于有人告诉我,hibernate中的会话就像jdbc中的连接