- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑以下服务(默认是事务性的)。玩家必须始终拥有一个帐户。没有至少一个对应帐户的玩家是错误状态。
class playerService {
def createPlayer() {
Player p new Player(name: "Stephen King")
if (!p.save()) {
return [code: -1, errors:p.errors]
}
Account a = new Account(type: "cash")
if (!a.save()) {
// rollback p !
return [code: -2, errors:a.errors]
}
// commit only now!
return [code: 0, player:p]
}
}
DomainObject.withTransaction {status ->
//stuff
if (someError) {
status.setRollbackOnly()
}
}
最佳答案
我不会称自己为专家,这个问题已经有一年多了,但我可以回答其中的一些问题,如果只是为了 future 的搜索者。我刚刚重构了一些 Controller 以使用服务以利用事务。
I have seen this pattern by experienced grails developers, and when I tell them that if creation of the account of the player fails for any reason, it wont rollback the player, and will leave the DB in an invalid state, they look at me like I am mad because grails handles rolling back the player because services are transactional right?
1.2 If an exception is thrown, you lose the p.errors - you lose the validation detail.
// in service
if (!email.save()) {
throw new ValidationException("Couldn't save email ${params.id}", email.errors)
}
// in controller
} catch (ValidationException e) {
def email = Email.read(id)
email.errors = e.errors
render view: "edit", model: [emailInstance: email]
}
1.4. use .save(failOnError: true) I am a big fan of using this, but its not appropriate everywhere. Sometimes you need to check the reason before going further, not throw an exception. Are the exceptions it can generate always checked, always unchecked, or either? I.e. will failOnError AWLAYS rollback, no matter what the cause? No one I have asked knows the answer to this, which is disturbing, they are using blind faith to avoid corrupted/inconsistent DBs.
failOnError
will cause save()
to throw a ValidationException
,所以是的,如果您在事务中并且没有检查该异常,则事务将被回滚。
failOnError
似乎不是“Grailsy”很多,可能是由于您列出的原因(例如,缺乏控制)。相反,您检查是否
save()
失败(
if (!save()) ...
),并据此采取行动。
- withTransaction
@Transactional
注释那个方法。 (除非您的开发人员也不喜欢注释,因为它们太“Java”;))。
@Transactional
标记一个方法,整体服务将变为非事务性。
3.1 The general case is we want every thing we do in a service method to roll back if anything in that service method cant be saved for any reason, or throws any exception for any reason (checked or unchecked).
rollbackFor
option to @Transactional
中列出它们来告诉您的服务回滚已检查的异常。 .
Or do people define lots of exception classes which subclass runtimeException, then explicit catch each of them in the controller to create the appropriate response? This is the old Java way, and our groovy devs pooh pooh this approach due to the amount of boiler plate code we will have to write.
private void validate(Long id, Closure closure) {
try {
closure()
} catch (ValidationException e) {
def email = Email.read(id)
email.errors = e.errors
render view: "edit", model: [emailInstance: email]
} catch (OtherException e) {
def email = Email.read(id)
flash.error = "${e.message}: ${e.reasons}"
render view: "show", model: [emailInstance: email]
} catch (Throwable t) {
flash.error = "Unexpected error $t: ${t.message}"
redirect action: "list"
}
}
def update(Long id, Long version) {
withInstance(id, version) { Email emailInstance ->
validate(emailInstance.id) {
emailService.update(emailInstance, params)
flash.message = "Email $id updated at ${new Date()}."
redirect action: "show", id: emailInstance.id
}
}
}
withInstance
是另一种类似的方法,它可以干掉检查是否存在和乐观锁定。)
关于exception - Grails 2.4.4 : How to reliably rollback in a complex service method,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28242153/
我是一名优秀的程序员,十分优秀!