Кэширование весеннего репозитория - PullRequest
0 голосов
/ 28 сентября 2018

Я пишу приложение с помощью Spring 5 и Hibernate.Есть служба, которая получает объект в состоянии, отличном от текущего.Он выполняет некоторую обработку и сохраняет объект в базе данных (используя Spring CrudRepository).

public void saveEntity(Entity entity) {
    ProcessingStatus processingStatus = doSomeProcessing(entity);
    if (processingStatus == ProcessingStatus.SUCCESS) {
        entity.setProcessingStatus(ProcessingStatus.SUCCESS);
        repository.save(entity);
    } else {
        Entity originalEntity = repository.findById(entity.getId());
        originalEntity.setProcessingStatus(ProcessingStatus.FAILURE);
        repository.save(originalEntity);
    }
}

Поэтому, если обработка прошла успешно, мы просто помечаем объект как статус успеха и сохраняем его.В противном случае любые изменения, связанные с новой версией сущности, не должны применяться.Таким образом, исходная сущность из репозитория извлекается, ее статус изменяется, а затем сохраняется.

Проблема в том, что строка

Entity originalEntity = repository.findById(entity.getId());

фактически извлекает уже измененный объект (вероятно, кешируется Hibernate?), а не оригинал из базы данных.Таким образом, originalEntity имеет тот же набор атрибутов, что и entity (полученный в качестве аргумента метода).Каков наилучший способ получения исходного объекта в таком случае?

1 Ответ

0 голосов
/ 28 сентября 2018

Полагаю, этот saveEntity метод аннотирован @Transactional.

. По этой причине, даже если явно не сохранено в repository.save(entity), у вас есть объект обновления, потому что вы находитесь в том же спящем режимесеанс.

Вы можете detach изменить свою сущность, а затем прочтете чистую ( ПРЕДУПРЕЖДЕНИЕ! , если ваша сущность еще не сохранена, вы получите null )

Для отсоединения и сущности вы должны ввести PersistenceContext в свой репозиторий

@Repository
public class EntityRepository {

    @PersistenceContext
    private EntityManager entityManager;

    public void detachOrderItem(Object object) {
        entityManager.detach(object);
    }
}

А затем вам нужно вызвать detach до findById

} else {

    entityRepository.detach(entity);

    Entity originalEntity = repository.findById(entity.getId());
    originalEntity.setProcessingStatus(ProcessingStatus.FAILURE);
    repository.save(originalEntity);
}

Другим более простым решением может быть запуск public void saveEntity(Entity entity) из транзакции (только вложенный метод может выполнять транзакцию)

...