我正在尝试使用Spring框架的@Async
功能来执行简单的索引任务。
我面临的问题是,我觉得异步函数中使用的EntityManager
已以某种方式从以前的调用中重用,因此我的数据不是最新的,有时会使用旧的数据。
这是我作为示例编写的代码。我的目标是在我使用Spring的ApplicationEventPublisher
发布事件后更新产品的数据并对其进行异步索引:
ProductService
@Service
class ProductService {
private final EntityManager entityManager;
private final ApplicationEventPublisher eventPublisher;
@Autowired
public ProductService(EntityManager entityManager,ApplicationEventPublisher eventPublisher) {
this.entityManager = entityManager;
this.eventPublisher = eventPublisher;
}
@Transactional
public void patchProduct (String id,ProductDto productDto) {
Product product = this.entityManager.find(Product.class,id);
product.setLabel(productDto.getLabel());
this.entityManager.flush();
this.eventPublisher.publishEvent(new ProductEvent(product,ProductEvent.EVENT_TYPE.UPDATED));
}
}
EventListener
@Component
public class ProductEventListener {
private final AsyncProcesses asyncProcesses;
@Autowired
public ProductEventListener (
AsyncProcesses asyncProcesses
) {
this.asyncProcesses = asyncProcesses;
}
@EventListener
public void indexProduct (ProductEvent productEvent) {
this.asyncProcesses.indexProduct(productEvent.getProduct().getPok());
}
}
AsyncProcesses
@Service
public class AsyncProcesses {
private final SlowProcesses slowProcesses;
@Autowired
public AsyncProcesses(SlowProcesses slowProcesses) {
this.slowProcesses = slowProcesses;
}
@Async
public void indexProduct (String id) {
this.slowProcesses.indexProduct(id);
}
}
慢处理
@Service
public class SlowProcesses {
private EntityManager entityManager;
private ProductSearchService productSearchService;
@Autowired
public SlowProcesses(EntityManager entityManager,NewProductSearchService newProductSearchService) {
this.entityManager = entityManager;
this.newProductSearchService = newProductSearchService;
}
@Transactional(readonly = true)
public void indexProduct (String pok) {
Product product = this.entityManager.find(Product.class,pok);
// this.entityManager.refresh(product); -> If I uncomment this line,everything works as expected
this.productSearchService.indexProduct(product);
}
}
正如您在 SlowProcesses 文件上看到的那样,如果我在entityManager中刷新产品对象,则会获得正确且最新的数据。如果没有,我可能会从以前的通话中获取旧数据。
在异步调用中使用EntityManager的正确方法是什么?为了使一切正常工作,我真的必须刷新所有对象吗?我在做别的事情吗?
感谢您通读