Java 在@Async调用中正确使用EntityManager
我试图使用Spring框架的Java 在@Async调用中正确使用EntityManager,java,spring,spring-data,Java,Spring,Spring Data,我试图使用Spring框架的@Async功能来执行简单的索引任务 我面临的问题是,我觉得异步函数中使用的EntityManager以某种方式从以前的调用中重用,因此我的数据不是最新的,有时使用旧数据 下面是我作为示例编写的代码。目标是在使用Spring的ApplicationEventPublisher发布事件后,更新产品数据并对其进行异步索引: 产品服务 @Service class ProductService { private final EntityManager entit
@Async
功能来执行简单的索引任务
我面临的问题是,我觉得异步函数中使用的EntityManager
以某种方式从以前的调用中重用,因此我的数据不是最新的,有时使用旧数据
下面是我作为示例编写的代码。目标是在使用Spring的ApplicationEventPublisher
发布事件后,更新产品数据并对其进行异步索引:
产品服务
@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());
}
}
异步进程
@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);
}
}
慢进程
@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的正确方法是什么?我真的必须刷新所有对象才能使一切正常工作吗?我还做错什么了吗?
感谢您通读,因为EntityManager的实例并不像Jordie所指出的那样是线程安全的,所以您可以尝试以下方法:
与其注入EntityManager,不如注入EntityManager工厂。然后从EntityManager工厂检索一个新的EntityManager实例,该实例仅在所讨论的方法期间使用。
EntityManager实例不是线程安全的。