1

Я реализует некоторые бизнес-логики/проверки с хранилищами Rest и JPA Spring Data с помощью валидаторов хранилища, как описано в:Spring Data Rest границы транзакции

http://docs.spring.io/spring-data/rest/docs/current/reference/html/#events.

После углубления в код SDR я заметил, что валидаторы (или, в более общем смысле, репозитарии) не вызывают транзакции.

Из исходного кода org.springframework.data.rest.webmvc.RepositoryEntityController:

private ResponseEntity<ResourceSupport> createAndReturn(Object domainObject, RepositoryInvoker invoker, 
      PersistentEntityResourceAssembler assembler, boolean returnBody) { 
     // validation logic is implemented in the listener, no transaction yet 
     publisher.publishEvent(new BeforeCreateEvent(domainObject)); 
     // invoker calls repository, which is wrapped in the transactional proxy, 
     // only then transaction begins 
     Object savedObject = invoker.invokeSave(domainObject); 
     publisher.publishEvent(new AfterCreateEvent(savedObject)); 

     PersistentEntityResource resource = returnBody ? assembler.toFullResource(savedObject) : null; 

     HttpHeaders headers = prepareHeaders(resource); 
     addLocationHeader(headers, assembler, savedObject); 

     return ControllerUtils.toResponseEntity(HttpStatus.CREATED, headers, resource); 
} 

Как видно в коде, слушатели не называется в рамках транзакции, что может привести к возможным проблемам непротиворечивости данных.

Я что-то упустил? Или структура просто неправильно устанавливает транзакционную границу?

+0

Я думаю, что он спроектирован таким образом. Событие «До» должно быть отправлено до сохранения и должно быть успешным независимо от успеха сохранения. Это общий подход весны, SDR только следует за ним. По моему мнению, невозможность приложить дополнительную логику к операциям репозитория делает всю концепцию едва пригодной. Поэтому мы должны использовать пользовательские контроллеры в 80% случаев. –

+0

Ну, я не совсем уверен, что события «до» не зависят от фактического вызова. В SDR [documentation] (http://docs.spring.io/spring-data/rest/docs/2.4.4.RELEASE/reference/html/#validation) предлагается использовать валидаторы как прослушиватели событий, таким образом фактический вызов репозитория зависит от успеха проверки. Во всяком случае, я понимаю, что базовая реализация Spring Data может не обязательно быть JPA, но заявить простую заметку о транзакциях в документах было бы действительно приятно :) –

+0

Если ваши слушатели событий должны принять участие в более крупной транзакции, то вы, скорее всего, не нужны прослушиватели событий, а полноценный сервис. В документации четко указано, что Spring Data REST просто предоставляет хранилища. – zeroflagL

ответ

1

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

Был аналогичный вопрос здесь: Handle spring-data-rest application events within the transaction

Особенно этот ответ обеспечивает обходной путь, который позволяет обернуть весь RepositoryEntityController метод в сделке - Я думаю, что это то, что вам нужно больше всего времени:

https://stackoverflow.com/a/30713264/5371736

+0

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

+0

_ «По крайней мере, обработчик событий должен выполняться в той же транзакции, что и метод репозитория» _ Почему? – zeroflagL

+4

Я думаю, что это общее требование, чтобы сделать некоторый дополнительный доступ к db в ваших событиях - например. выполните некоторый аудит. И вы легко достигнете точки, когда вы хотите, чтобы ваше обновление было откатным, когда аудит завершится неудачей. Мы часто отправляем сообщения с использованием Spring-amqp после обновлений или создаем - и если отправка сообщений не выполняется, мы также хотим отменить транзакцию и наоборот. –