Откат транзакции в сервисе Grails - PullRequest
12 голосов
/ 05 июня 2010

Я обновлял все свои сервисы, чтобы они были транзакционными, используя возможность Grail для отката, когда в сервисе возникает исключение RuntimeException. Я в большинстве случаев делаю это:

def domain = new Domain(field: field)
if (!domain.save()) {
   throw new RuntimeException()
}

В любом случае, я хотел убедиться, что это действительно откатит транзакцию ... это заставило меня задуматься о том, было ли в этот момент она уже зафиксирована ... Также, если нет, установит ли параметр flush: true ли это изменить? Я не очень знаком с тем, как Spring / Hibernate делает все это:)

Ответы [ 2 ]

15 голосов
/ 05 июня 2010

Да, это будет сделано.

Транзакции в Grails по умолчанию обрабатываются на уровне метода Service. Если метод возвращается нормально, тогда транзакция будет зафиксирована, если выдается RuntimeException, транзакция будет откатываться.

Обратите внимание, что это означает, что даже если вы используете flush: true при сохранении объекта в методе сервера, изменения в БД все равно будут отменены, если вы выбросите RuntimeException.

Например:

class MyService {

 def fiddle(id,id2){
   def domain = Domain.findById(id)

   domain.stuff = "A change"
   domain.save( flush:true ) // will cause hibernate to perform the update statements

   def otherDomain = OtherDomain.findById(id2)      

   otherDomain.name = "Fiddled"

   if( !otherDomain.save( flush:true )){ // will also write to the db
     // the transaction will be roled back 
     throw new RuntimeException("Panic what the hell happened")
   }                                                           
 }
}

То, что я не на 100% ясен с Grails, - это то, что происходит, если в прямом мире Java / Spring выдается проверенное исключение. По умолчанию поведение инициатора транзакции фиксирует транзакцию, хотя это может быть переопределено в конфигурации. .

Примечание: есть предостережение, и ваша база данных должна поддерживать транзакции в таблицах, которые вы обновляете. Да, это тыкать в MySQL:)

Это также относится к методу Domain.withTransaction.

2 голосов
/ 21 июля 2016

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

Что мне не совсем ясно с Grails, так это то, что произойдет, есливыброшено исключение

По умолчанию исключение НЕ должно быть проверено, иначе транзакция не будет откатана.Очевидно, это Spring.

Если вы действительно хотите проверить исключения для метода, вы можете явно пометить метод службы как @Transactional и использовать аргумент rollbackFor для вывода спискакакие исключения все еще должны вызывать откат.(Обратите внимание, что я на самом деле не проверял это.)

Имейте в виду, однако, что пометка любого одного метода в сервисе с помощью @Transactional отключает автоматическое обертывание других его методов транзакцией.Так что, если вы делаете это для одного, вы должны сделать это для всех них.Убедитесь, что вам действительно нужно , чтобы объявить эти проверенные исключения;)

Подробнее об этом можно прочитать на http://docs.grails.org/latest/guide/services.html.

...