我需要创建一个过程,该过程将查询Web服务以提取信息,然后将数据保存在数据库中。但是,由于此过程非常耗时,因此我想使其在后台运行。

当前,我有一个ProcessHandler,它由UI中的按钮调用。该处理程序创建一个Thread,该CC应该在后台运行该进程。但是,我收到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定义为config xml文件(之一)中的bean时的遗留物。

有人可以通过给我一些有关如何解决此问题的提示来帮助我吗?

最佳答案

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

由于ProcessHandler是合法的bean,因此我将执行以下操作:

1)创建一个seaparate服务类,该类将管理者作为依赖项,并使用@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();


现在,您的操作应该是事务性的,并且应该在会话中进行。

09-04 05:45