使用Spring Data和Hibernate时如何正确执行后台线程?

我正在构建一个使用Spring Data和Hibernate的简单Tomcat Web应用程序。有一个端点要做很多工作,因此我想将工作卸载到后台线程,以便在完成工作时Web请求不会挂起10分钟以上。因此,我在组件扫描的程序包中编写了新服务:

@Service

public class BackgroundJobService {

@Autowired

private ThreadPoolTaskExecutor threadPoolTaskExecutor;

public void startJob(Runnable runnable) {

threadPoolTaskExecutor.execute(runnable);

}

}

然后ThreadPoolTaskExecutor在Spring中进行配置:

<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">

<property name="corePoolSize" value="5" />

<property name="maxPoolSize" value="10" />

<property name="queueCapacity" value="25" />

</bean>

这一切都很好。但是,问题来自于hibernate。在我的可运行内部,查询仅完成一半。我可以:

MyObject myObject = myObjectRepository.findOne()

myObject.setSomething("something");

myObjectRepository.save(myObject);

但是,如果我有延迟加载的字段,它将失败:

MyObject myObject = myObjectRepository.findOne()

List<Lazy> lazies = myObject.getLazies();

for(Lazy lazy : lazies) { // Exception

...

}

我收到以下错误:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.stackoverflow.MyObject.lazies, could not initialize proxy - no Session

因此,对我来说(hibernate新手),新线程在这些自制线程上没有会话,但是Spring Data会自动为HTTP请求线程创建新会话。

  • 有没有办法从会话中手动启动新会话?
  • 还是一种告诉线程池为我做的方法?
  • 做这种工作的标准做法是什么?

    通过从@Transactional方法内部做所有事情,我已经能够解决该问题,但是我很快就知道这不是一个很好的解决方案,因为这不能让我使用对Web请求来说效果很好的方法。

回答:

使用Spring,你不需要自己的执行程序。一个简单的注释@Async将为你完成工作。只需heavyMethod在你的服务中为其添加注释并返回void或Future对象,你将获得一个后台线程。我会避免在控制器级别使用异步注释,因为这将在请求池执行程序中创建一个异步线程,并且你可能会用完“请求接受器”。

延迟异常的问题来自你怀疑来自没有会话的新线程。为避免此问题,你的异步方法应处理完整的工作。不要提供先前加载的实体作为参数。该服务可以使用EntityManager,也可以是事务性的。

我自己不会合并@Async,@Transactional因此我可以以任何一种方式运行该服务。我只是围绕服务创建一个异步包装器,并在需要时使用该包装器。(例如,这简化了测试)

@Service

public class AsyncService {

@Autowired

private Service service;

@Async

public void doAsync(int entityId) {

service.doHeavy(entityId);

}

}

@Service

public class Service {

@PersistenceContext

private EntityManager em;

@Transactional

public void doHeavy(int entityId) {

// some long running work

}

}

以上是 使用Spring Data和Hibernate时如何正确执行后台线程? 的全部内容, 来源链接: utcz.com/qa/401445.html

回到顶部