【问题标题】:how can i rollback all the transactions if one domain save fails?如果一个域保存失败,我如何回滚所有事务?
【发布时间】:2014-11-20 03:17:31
【问题描述】:

我想知道是否可以回滚多个更改。

例如

假设在控制器内部我连续保存了三个域。

domain1.save(flush:true)
domain2.save(flush:true)
domain3.save(flush:true)

现在我希望行为是这样的,如果这三个保存中的任何一个失败,那么成功的保存也应该回滚,即我希望所有这三个保存构成一个事务。我想知道是否有办法在grails中做到这一点?我发现 withTransaction 但这似乎与特定域相关联。谢谢!寻求帮助。

【问题讨论】:

    标签: grails transactions grails-orm


    【解决方案1】:

    withTransaction 与它所调用的域类无关,但它有点像 hack,因为它可以让你做一些愚蠢的事情,比如控制器中的事务持久性。控制器应该专注于与 HTTP 相关的内容,并将实际工作委托给服务,默认情况下这些服务很方便地进行事务处理,除非您为特定服务禁用它。

    将所有数据库更新和业务逻辑移至服务,并保持控制器轻量级并专注于提取请求参数和进行数据绑定(例如,通过int foo = params.int('foo') 将字符串“12453”转换为 int 12453,并使用该数据调用服务方法,然后将它们的返回值传递给要呈现的视图。控制器应该只是路由器。

    如果需要,您可以使用@Transactional 注释来自定义事务如何为整个服务或每个方法工作,但默认情况下,即使没有任何注释,服务也是事务性的。你可以在一个方法中做尽可能多的工作,它会全部成功或全部回滚。我什至在事务方法中进行单个更新/删除/插入,以便以后根据需要使事情变得更复杂,而无需考虑事务。如果所有数据库更改始终都是事务性的,那么事情通常会运行得更好。

    【讨论】:

    • 谢谢!伯特。再澄清一件事。在上面的例子中,三个域是独立的。那么,服务类是否会检测到这一点并确保全部成功或都不成功。
    • 是的,只要它们使用相同的DataSource,它们就会使用相同的 Hibernate Session 和 JDBC Connection。如果域使用混合数据源,则需要使用两阶段提交,但如果使用grails.org/plugin/atomikos 插件,这很容易。我有一个在线演讲,讨论 Grails 中的事务 - 大约 45 分钟:2013.gr8conf.eu/Presentations/Grails-Transactions
    【解决方案2】:

    伯特,谢谢你的解释。它有助于。 MVC 成为 MVCS。 但是,请再澄清一点: 我曾经明白,即使我没有调用 .save(),控制器也会想要保存更新的类(在绑定新参数之后)_on_his_own_。 这将如何干扰中间调用的服务中已经处理/保存的类? 或者控制器只从一个字符串创建一个整数并将更正的参数进一步传递给服务,在那里做所有的事情,控制器在 MVC 世界中早些时候做的?

    编辑和后期反应: 很抱歉没有足够的声誉来发表评论

    【讨论】:

    • 这不应该是一个答案
    猜你喜欢
    • 1970-01-01
    • 2019-03-10
    • 2019-02-09
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    相关资源
    最近更新 更多