2017-02-16 9 views
1

Откат делается здесь, как и ожидалось:Grails (2,3) @Transactional не откатить

@Transactional(propagation = Propagation.REQUIRES_NEW) 
def test1() { 
    def dummy = new Dummy(name: "test1") 
    dummy.save() 
    throw new RuntimeException("test1!") 
} 

Но здесь нет - что, вероятно, неправильно - попытаться/поймать не должны влиять на поведение:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
def test2() { 
    def dummy = new Dummy(name: "test2") 
    dummy.save() 
    try { 
    throw new RuntimeException("test2!") 
    } catch (all) { 
    println all.message 
    } 
} 

ответ

1

может быть, вы не поняли цель попытке поймать или, может быть, вы просто имея шаткий момент:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
def test2() { 
    //you may be doing other stuff here 
    //but now about to do some transaction work 
    //so lets wrap this method around a try catch 
    try { 
    //this is happening 
    def dummy = new Dummy(name: "test2") 
    dummy.save()  
    } catch (Exception all) { // or catch (Throwable all) { 
    // if something went wrong in above save method 
    //should be caught and runtime exception means roll back 
    throw new RuntimeException("test2!" +all?.toString()) 
    } 
} 

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

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

I did a sample project years back here надеюсь, что это помогает

eitherway те у кого-то эксперименты и на самом деле не так, как вы бы идти об этом правильное кодирование, я имею в виду, что это довольно странно, необычный способ делать вещи, и короче он просто пытаясь заставить его выбросить исключение во время выполнения, поэтому запуск откат. Я придерживаюсь своего предложения в ответе на то, что вы хотите сделать один попытку поймать в контроллере. Это пытается зафиксировать как ошибки проверки, так и недостатки в случае отказа какой-либо данной транзакционной транзакции. Something like this, но, вероятно, гораздо больше работы по захвату всех конкретных проблем и возврату на исходную страницу с основными проблемами - теперь также откат транзакции.

+0

Я ожидал, что прокси-сервер узнает исключение в любом случае. См. Тест 2 здесь: http://devhobbs.blogspot.de/2015/04/grailsgorm-transactions.html (результат теста 2: запись не записана. Исключение отменяется.) –

+0

только для того, чтобы быть в курсе, что вы находитесь в службе? '@Transactional (распространение = Propagation.REQUIRES_NEW) def test1() {' находится в сервисе?а не с контроллером, так как если вы посмотрите на пример, который вы предоставили '@Transactionalclass BookService {' – Vahid

+0

, я обновил свой анвс, так как мой комментарий назад о вашем примере и т. д. слишком долго проверяет обновленный ответ – Vahid

2

По умолчанию @Transactional обертывает метод таким образом, что любое исключенное исключение (а именно, RuntimeException) приведет к откату транзакции.

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

Следует отметить, что вы можете указать, что транзакционная оболочка должна откатывать транзакции, если другие исключения выбрасываются (и распространяются на обертку). Вы можете сделать это с помощью параметра аннотации rollbackFor.

Например,

@Transactional(rollbackFor=Throwable.class) 
void doTransactionalWork() throws MyException { ... } 

приведет к транзакции быть откат, если любой Throwable, распространяется до обертки, даже те, которые проверяются (а именно, MyException)

Это должно быть поведение любого метода @Transactional, независимо от того, создаете ли вы новую транзакцию или наследуете существующий транзакционный контекст.

Смежные вопросы