我有一个服务,在那里将大量数据保存到db。
使用MYSQL
我用过这样的
Domain1.withTransaction {text->
def domain1=//Create my domain object to save
if(!domain1.save()){
domain1.errors.each {
println it
}
throw new RuntimeException('unable to save domain1')
}
Domain2.withTransaction {text->
def domain2=//Create my domain object to save
if(!domain2.save()){
domain2.errors.each {
println it
}
throw new RuntimeException('unable to save domain2')
}
我的问题是如果在保存domain2时出现任何问题我还需要回滚domain1保存 我需要从db中删除domain1。
答案 0 :(得分:3)
服务工件不允许使用程序化事务处理,而是允许自动事务处理。这通常会使代码更清晰,更易于维护。
当save()强制抛出RuntimeException时,也可以使用failOnError:true。
以下示例:
class SomeService {
static transactional = false
def serviceMethod() {
def domain1=//Create my domain object to save
def domain2=//Create my domain object to save
domain1.save(failOnError:true)
domain2.save(failOnError:true)
}
}
<强>更新强>
在我阅读了另一个主题的回复之后,我正在重新审视这个主题。 Grails Integration Test Does NOT Rollback
请验证您的方言是否设置为InnoDB,因为MyISAM表不是事务性的。这是在Config.groovy
dataSource {
dialect= org.hibernate.dialect.MySQLInnoDBDialect
...
}
答案 1 :(得分:1)
尝试删除Domain2.withTransaction {text-&gt;部分。 您第一次通话时已进入交易。 如果你在括号内做进一步的工作,你应该保持在同一个事务中,如果你在检查domain2之后抛出异常,应该回滚domain1。
答案 2 :(得分:0)
将Domain2.withTransaction
闭包放在Domain1.withTransaction
闭包内,因此Domain2事务中的错误将回滚Domain1和Domain2事务
喜欢这个
Domain1.withTransaction {
//....
Domain2.withTransaction {
//....
}
}
答案 3 :(得分:0)
如果您只想要在抛出未处理的未经检查的异常时回滚单个事务,则不要启动嵌套事务。必要的代码更改如下所示:
Domain1.withTransaction {text->
def domain1=//Create my domain object to save
if (!domain1.save()) {
domain1.errors.each {
println it
}
throw new RuntimeException('unable to save domain1')
}
def domain2=//Create my domain object to save
if (!domain2.save()) {
domain2.errors.each {
println it
}
throw new RuntimeException('unable to save domain2')
}
}