Правильное использование EntityManager в вызове @Async - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь использовать возможности @Async среды Spring для выполнения простой задачи индексации.

Проблема, с которой я сталкиваюсь, заключается в том, что я чувствую, что EntityManager используется в моей функции Asyncкаким-то образом используется из предыдущих вызовов, поэтому мои данные не обновляются, а иногда используются старые данные.

Вот код, который я написал в качестве примера. Цель состоит в том, чтобы обновить данные продукта и асинхронно проиндексировать их после публикации события с использованием 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);
    }
}

SlowProcesses

@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 в асинхронном вызове? Мне действительно нужно обновить все мои объекты, чтобы все работало? Я что-то не так делаю?

Спасибо, что прочитали

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...