在@Async调用中正确使用EntityManager

我正在尝试使用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的正确方法是什么?为了使一切正常工作,我真的必须刷新所有对象吗?我在做别的事情吗?

感谢您通读

yaozhiying 回答:在@Async调用中正确使用EntityManager

由于Jordie指出,由于EntityManager实例不是线程安全的,因此您可能需要尝试以下方法:
而不是注入EntityManager,而是注入EntityManagerFactory。然后从EntityManagerFactory中检索一个新的EntityManager实例,该实例仅在所讨论方法的持续时间内使用。

本文链接:https://www.f2er.com/3161551.html

大家都在问