Как обработать несколько обновлений сущностей в одной транзакции в Spring Data REST - PullRequest
1 голос
/ 27 марта 2020

Есть ли у кого-нибудь идеи о том, как обрабатывать несколько обновлений сущностей в одной транзакции в Spring Data REST ? То же самое можно сделать в методах контроллера Spring с помощью аннотации @Transactional. Если я прав, Spring Data REST выполняет каждое событие выполнения в отдельных транзакциях. Таким образом, несколько обновлений сущностей не могут быть обработаны надлежащим образом.

У меня возникают проблемы с обновлением 2 сущностей (AB C и PQR) в рамках одной транзакции и откатом сущности AB C, когда сущность PQR не удалось.

// ABC repository
    @RepositoryRestResource
    public interface ABCEntityRepository extends MongoRepository<ABC, String> {
    }

// PQR repository
    @RepositoryRestResource
    public interface PQREntityRepository extends MongoRepository<PQR, String> {
    }

// ABC repository handler
    @RepositoryEventHandler
    public class ABCEventHandler {

        @Autowired
        private PQREntityRepository pqrEntityRepository;


        @HandleBeforeSave
        public void handleABCBeforeSave(ABC abc) {
          log.debug("before saving ABC...");
        }

        @HandleAfterSave
        public void handleABCAfterSave(ABC abc) {
          List<PQR> pqrList = pqrEntityRepository.findById(abc.getPqrId());

          if (pqrList != null && !pqrList.isEmpty()) {
            pqrList.forEach(pqr -> {
              // update PQR objects
            }
          }

          // expect to fail this transaction
          pqrEntityRepository.saveAll(pqrList);
        }
    }

, так как метод @HandleAfterSave выполняется в отдельной транзакции, вызов метода HandleAfterSave означает, что обновление объекта AB C уже завершено и поэтому не может выполнить откат. Любое предложение справиться с этим?

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Spring Data REST не думает в сущностях, он думает в совокупностях. Агрегат - это термин, исходящий из доменного дизайна, который описывает группу объектов, для которых применяются определенные бизнес-правила. Возьмите заказ вместе с его позициями, например, и бизнес-правилом, которое определяет минимальную стоимость заказа, которая должна быть достигнута.

Ответственность за управление ограничениями совпадает с другим аспектом, который включает агрегаты в DDD, который такая строгая согласованность должна / может приниматься только для изменений самого агрегата. Ожидается, что изменения в нескольких (разных) агрегатах в конечном итоге будут последовательными. Если вы перенесете это в технологию, целесообразно применить средства строгой согласованности - читай: транзакции - только к отдельным агрегатам.

Так что нет короткого ответа на ваш вопрос. Структура репозитория, которую вы здесь показываете, фактически превращает и ABCEntity, и PQREntity в агрегаты (поскольку репозитории существуют только для агрегатных корней). Это означает, что OOTB Spring Data REST не поддерживает их обновление в одном транзакционном HTTP-вызове.

При этом Spring Data REST позволяет объявлять пользовательские ресурсы, которые могут взять на себя ответственность за это. Аналогично тому, что показано здесь , вы можете просто добавить ресурсы на дополнительные маршруты, чтобы полностью реализовать то, что вы себе представляете.

Spring Data REST не предназначен для создания полного HTTP API из коробка. Он предназначен для реализации определенных шаблонов REST API, которые обычно встречаются в HTTP API и, скорее всего, будут частью вашего API. Он построен так, чтобы вам не приходилось тратить время на размышления о простых случаях и нужно только подключать пользовательский код для сценария ios, подобный тому, который вы описали, предполагая, что то, что вы планируете делать здесь, является хорошей идеей в первую очередь. , Очень часто подобные запросы приводят к выводу, что совокупный дизайн требует доработки.

PS: я видел, что вы пометили этот вопрос spring-data-mongodb. По умолчанию Spring Data REST не поддерживает транзакции MongoDB, потому что они им не нужны. Границы документов MongoDB обычно совпадают с границами агрегатов, и обновления в любом документе в любом случае находятся в пределах c.

0 голосов
/ 05 апреля 2020

Я не уверен, что правильно понял ваш вопрос, но я попробую.

Я бы посоветовал иметь услугу как с Repositories, так и с методом, аннотированным @Transactional, который обновляет все, что вы хотите.

Таким образом, если транзакция не удастся где-либо внутри метода, все будет выполнено откат.

Если это не отвечает на ваш вопрос, уточните, и я постараюсь помочь.

...