Как предотвратить исключения, вызывающие откат транзакции в Grails?

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

в моей службе у меня есть что-то вроде

updateSomething(domainObj) {
    def oldFilename = domainObj.filename
    def newFilename = getNewFilename()

    domainObj.filename = newFilename
    domainObj.save(flush: true)

    try {
        cleanUpOldFile(oldFilename)
    } catch (cleanupException) {
        // oh well, log and swallow
    }
}

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

Как ограничить транзакцию области до завершения очистки или есть другой способ получить исключение очистки, чтобы не вызвать откат?

просто для записи я использую Grails 2.1.1

2 ответов


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

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

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

так что у вас есть несколько вариантов. Аннотации updateSomething as @Transactional но не аннотации cleanUpOldFile:

import org.springframework.transaction.annotation.Transactional

@Transactional
def updateSomething(domainObj) {
...
}

def cleanUpOldFile(...) {
   ...
}

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

@Transactional(noRollbackFor=[FooException, BarException])
def cleanUpOldFile(...) {
   ...
}

кроме @Burt Beckwithответ, если у вас есть служба, где вы просто не хотите транзакций (что я на самом деле сделал в моем случае), вы можете отключить транзакции по всем общедоступным методам, добавив

static transactional = false

в класс обслуживания.