Зачем использовать » Распространение.ТРЕБУЕТСЯ` избыточное `Распространение.ВЛОЖЕННЫЕ`?

#java #spring #spring-data

Вопрос:

С Spring по умолчанию используются транзакции Propogation.REQUIRED , но мне это кажется довольно странным выбором. Если мы игнорируем существование транзакций, то это очень нормальный шаблон, чтобы поймать исключение и реализовать запасной вариант. Например, в очень простой форме:

 public void doSomethingFirst() {} public void doSomethingElse() {}  public void doSomethingWithFallback() {  this.doSomething();  try {  this.doSomethingElse();  } catch (Exception e) {  this.fallback();  } }  

Однако Propagation.REQUIRED это нарушает:

 public void doSomethingFirst() { } @Transactional(propagation = Propagation.REQUIRED) public void doSomethingElse() { }  @Transactional(propagation = Propagation.REQUIRED) public void doSomethingWithFallback() {  this.doSomethingFirst();  try {  this.doSomethingElse();  } catch (Exception e) {  this.fallback();  } }  

Теперь, если doSomethingElse произойдет сбой, он отметит транзакцию только как откат. Даже несмотря на то, что у нас есть отличный запасной вариант, вся транзакция будет откатана, и мы ничего не сможем сделать, чтобы остановить это.

«Исправление» для этого заключается в использовании NESTED вместо REQUIRED (по крайней мере, в doSomethingElse ):

 public void doSomethingFirst() { } @Transactional(propagation = Propagation.NESTED) public void doSomethingElse() { }  @Transactional(propagation = Propagation.NESTED) public void doSomethingWithFallback() {  this.doSomethingFirst();  try {  this.doSomethingElse();  } catch (Exception e) {  this.fallback();  } }  

Теперь мы используем точки сохранения, и в случае doSomethingElse сбоя это приведет только к откату doSomethingElse .

Мне кажется NESTED , что это поведение, которого мы почти всегда хотим, и я изо всех сил пытаюсь придумать какой-либо вариант использования, который REQUIRED был бы предпочтительнее. REQUIRED запрещает вызывающему абоненту восстанавливаться после ошибок, что обычно является плохой идеей.

Но, учитывая, что REQUIRED это значение по умолчанию, и оно NESTED почти никогда не используется, наверняка должна быть какая-то причина, по которой мы должны использовать REQUIRED его снова NESTED .

В каких случаях мы должны REQUIRED предпочесть NESTED ?

Комментарии:

1. То @Transactional , что на doSomethingElse то, бесполезно. Не каждая база данных поддерживает точки сохранения, в то время как все они поддерживают REQUIRED . Кроме того, он также используется по умолчанию для транзакций для EJBs, и Spring соответствует этому с момента своего создания. Кроме того, то, что вы считаете базовой практикой (т. Е. резервным вариантом), не является таким уж базовым или распространенным. Когда вы пишете что-то, что либо терпит неудачу, либо преуспевает, я не хочу делать что-то еще. Если бы вы действительно хотели, вы могли бы сделать это в новой транзакции вместо того, чтобы также использовать точки сохранения.

2. @Transactional Включение doSomethingElse определенно не бесполезно. doSomethingElse может выполнять несколько операций, требующих транзакции, и может использоваться в нескольких контекстах. И в любой достаточно сложной системе вы обязательно будете использовать резервные варианты, где это уместно. Новая транзакция имеет совершенно другие характеристики, хотя это вовсе не замена вложенной

3. Несмотря на это, меня втягивают в детали, но в этом нет смысла. Вопрос в том , когда REQUIRED следует предпочесть NESTED , и в своем комментарии вы обратились к этому только с поддержкой БД. Итак, давайте перефразируем это немного по-другому: если ваша БД поддерживает точки сохранения, зачем использовать REQUIRED вместо ВЛОЖЕННЫХ?

4. Ваш вопрос касается значения по умолчанию, на который был дан ответ, потому что он соответствует поведению EJB по умолчанию и что не все базы данных поддерживают это. Кроме того, то, что вы считаете обычным делом, не так распространено, как вы думаете. Наконец, большинству проектов требуется операция «все или ничего», а не полная или частичная операция, которую вы получили бы с ВЛОЖЕННЫМИ.