Как предотвратить исключения, вызывающие откат транзакции в 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
в класс обслуживания.