【问题标题】:Background thread throwing HibernateException - "No Hibernate Session bound to thread..."后台线程抛出 HibernateException - “没有绑定到线程的 Hibernate 会话......”
【发布时间】:2023-03-13 02:20:02
【问题描述】:

我需要创建一个进程来查询 Web 服务以提取信息,然后将数据保存在我的数据库中。但是,由于这个过程非常耗时,我想让它在后台运行。

目前,我有一个ProcessHandler,它由 UI 中的按钮调用。此处理程序创建一个Thread,它应该在后台运行该进程。但是,我收到了 HibernateException 和消息 No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

我在一个配置xml文件(有几个)中定义了ProcessHandler,如下(这是一个非常通用的定义):

<bean class="com.project.ProcessHandler" parent="parentHandler" />

ProcessHandler内部,调用这个过程的代码也很通用:

Thread t = new Thread(new WorkerThread(alphaManager, bravoManager, charlieManager));
t.start();

这是WorkerThread的当前实现:

public class WorkerThread implements Runnable {

    private Manager alphaManager;
    private Manager bravoManager;
    private Manager charlieManager;

    public WorkerThread() {
        this.alphaManager = null;
        this.bravoManager = null;
        this.charlieManager= null;
    }

    public WorkerThread(Manager alphaManager, Manager bravoManager, Manager charlieManager) {
        this.alphaManager = alphaManager;
        this.bravoManager = bravoManager;
        this.charlieManager= charlieManager;
    }

    @Override
    public void run() {
        // code to query webservice and extract data...

        saveToDbMethod(data);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    private void saveToDbMethod(String data) {
        // code to process data...

        alphaManager.save(entityA);
        bravoManager.save(entityB);
        charlieManager.save(entityC);
    }
}

默认构造函数是我尝试将 WorkerThread 定义为我的配置 xml 文件(之一)中的 bean 时留下的。

谁能帮我解决这个问题?

【问题讨论】:

    标签: java spring multithreading hibernate


    【解决方案1】:

    问题是您手动创建线程并期望它的行为类似于 spring 托管 bean。

    由于ProcessHandler 是一个合法的bean,我要做的就是:

    1) 创建一个独立的服务类,它将管理器作为依赖项和 @Transactional 方法:

    @Service
    public class Service{
    
        private Manager alphaManager;
        private Manager bravoManager;
        private Manager charlieManager;
    
        public Service(Manager alphaManager, Manager bravoManager, Manager charlieManager) {
            this.alphaManager = alphaManager;
            this.bravoManager = bravoManager;
            this.charlieManager= charlieManager;
        }
    
        @Transactional(propagation = Propagation.REQUIRED)
        private void saveToDbMethod(String data) {
            // code to process data...
    
            alphaManager.save(entityA);
            bravoManager.save(entityB);
            charlieManager.save(entityC);
        }
    }
    

    2)Service注入ProcessHandler

    <bean class="com.project.ProcessHandler" parent="parentHandler">
       <property name="service" ref="service">
    </bean>
    

    3) 最后将Service 传递给WorkerThread

    public class WorkerThread implements Runnable {
    
        private Service service;
    
        public WorkerThread(Service service) {
            this.service = service;
        }
    
        @Override
        public void run() {
            // code to query webservice and extract data...
    
            service.saveToDbMethod(data);
        }
    }
    

    和:

    Thread t = new Thread(new WorkerThread(service));
    t.start();
    

    现在您的操作应该是事务性的并且在会话内。

    【讨论】:

    • 我应该如何在配置中定义service
    • 我在ProcessHandler 的定义正下方定义了它:&lt;bean id="service" class="com.project.Service" /&gt; 但是,我得到org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'service' is defined
    • 我已经设法通过遵循这个解决方案解决了我的问题,之后进行了一些故障排除。我将在后续的 cmets 中详细介绍我的故障排除过程。
    • 我收到此错误 - org.springframework.beans.factory.NoSuchBeanDefinitionExcept‌​ion: No bean named 'service' is defined。我通过在配置文件中定义 service 来修复它,该配置文件将在定义 ProcessHandler 之前被读取,如下所示:
    猜你喜欢
    • 2011-05-09
    • 2011-12-11
    • 2010-11-19
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    相关资源
    最近更新 更多