Tôi đang xây dựng một ứng dụng web Tomcat đơn giản đang sử dụng Spring Data và Hibernate. Có một điểm kết thúc thực hiện rất nhiều công việc, vì vậy tôi muốn tải công việc xuống một chuỗi nền để yêu cầu web không treo trong hơn 10 phút trong khi công việc đang được thực hiện. Vì vậy, tôi đã viết một dịch vụ mới trong một gói phần-scan'd:Làm cách nào để thực hiện đúng chuỗi nền khi sử dụng Dữ liệu Spring và Hibernate?
@Service
public class BackgroundJobService {
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
public void startJob(Runnable runnable) {
threadPoolTaskExecutor.execute(runnable);
}
}
Sau đó có ThreadPoolTaskExecutor
cấu hình trong mùa xuân:
<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>
Đây là tất cả làm việc tuyệt vời. Tuy nhiên, vấn đề đến từ Hibernate. Bên trong runnable của tôi, truy vấn chỉ có một nửa công việc. Tôi có thể làm:
MyObject myObject = myObjectRepository.findOne()
myObject.setSomething("something");
myObjectRepository.save(myObject);
Nhưng nếu tôi có các trường lười nạp, nó không thành công:
MyObject myObject = myObjectRepository.findOne()
List<Lazy> lazies = myObject.getLazies();
for(Lazy lazy : lazies) { // Exception
...
}
tôi nhận được lỗi sau:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.stackoverflow.MyObject.lazies, could not initialize proxy - no Session
Vì vậy, có vẻ như với tôi (Hibernate newbie) rằng luồng mới không có phiên làm việc trên các luồng được tạo trong nhà này, nhưng Spring Data sẽ tự động tạo các phiên mới cho các chuỗi yêu cầu HTTP.
- Có cách nào để bắt đầu phiên mới theo cách thủ công từ trong phiên không?
- Hoặc một cách để cho hồ bơi chủ đề làm điều đó cho tôi?
- Thực hành tiêu chuẩn để thực hiện loại công việc này là gì?
Tôi đã có thể làm việc xung quanh nó một chút bằng cách làm mọi thứ từ bên trong một phương pháp @Transactional
, nhưng tôi nhanh chóng tìm hiểu đó không phải là một giải pháp rất tốt, vì điều đó không cho phép tôi sử dụng các phương pháp hoạt động tốt cho các yêu cầu web.
Cảm ơn.
Một phần của vấn đề là, tôi muốn có thể cập nhật trạng thái công việc trong khi nó đang chạy. Vì vậy, nếu tôi bọc tất cả trong một giao dịch, trạng thái không cập nhật cho đến khi cam kết ngoài cùng cam kết. Trừ khi tôi đang thiếu một cái gì đó ở đây ... đó là hoàn toàn có thể :) – Joel
Bạn có thể hiển thị lớp thực hiện Runnable của bạn và có thể ObjectRepository của bạn? Tôi cũng rất tò mò về cách thức và vị trí bạn dự định xuất bản các cập nhật trạng thái. Không rõ ràng với các ứng dụng web dựa trên http. – alobodzk
Cụ thể để cập nhật trạng thái tiến trình: sử dụng giao dịch lồng nhau. Đảm bảo rằng nhà cung cấp JPA của bạn hỗ trợ họ. – Virmundi