技术原因是不在Config.groovy中将grails.gorm.autoFlush和grails.gorm.failOnError设置为true?

时间:2011-01-15 22:32:56

标签: grails

除了这样做的明显性能影响之外,在grails.gorm.autoFlush = true中设置grails.gorm.failOnError = trueConfig.groovy有什么好的技术原因?

3 个答案:

答案 0 :(得分:18)

GORM是Hibernate的包装器(至少是其中一个实现 - 现在还有各种NoSQL实现,比如Redis)。通过将autoFlush设置为true,您拒绝Hibernate优化对数据库进行的调用的机会。例如,当单个插入可能已足够时,您可能会导致它稍后插入更新。这没有任何本质上的坏处,它只是没有必要而且效率较低。 Hibernate非常聪明,可以知道什么时候需要写入数据库并且可以优化 - 你已经抽象出了这个问题。

设置failOnError会导致save在您尝试保存未验证的域对象时抛出异常。在构建涉及从用户输入创建对象的应用程序时,对象不能验证是很正常的 - 缺少输入,格式错误等。应该为异常和错误保存异常处理 - 它不应该用于应用程序的正常流程。 save()在成功保存对象时返回对象,否则返回null,这为您提供了一种更方便的方法来处理验证作为应用程序流的一部分,而不是将try-catch块放在一起。

Peter Ledbrook(Grails in Action的作者)撰写了一系列很多“GORM Gotchas”文章,其中更详细地讨论了其中的一些问题 - 非常值得一读:part 1,{ {3}}& part 2

答案 1 :(得分:11)

我同时使用并相信我有很好的理由想与您分享。

为什么要使用grails.gorm.autoFlush = true

当我调用save()时没有真正保存实体/域是因为我没有告诉API要做什么。当Hibernate在执行之前在16行上刷新并且给调试带来痛苦时,它会引起许多麻烦。你的团队不是Java开发人员,这很痛苦。

Grails从Ruby借用了Active Record Pattern(直接调用了持久化方法,比如domain.save),但是当调用save()时,Ruby确实做了持久性,但是Grails没有,因为它们隐藏了'Hibernate Session'来自API用户/开发人员。我们可以使用此配置参数解决GORM的严重 泄漏抽象 失败。

一旦设置好,如果你真的需要Hibernate的工作单元模式,它链接SQL调用并且出于性能原因只执行一次,只需在需要时使用domain.save(flush:false)

为什么要使用grails.gorm.failOnError = true

永远不要向用户隐藏异常。所有优秀的Java程序员都知道这一点。如果你“确实”需要隐藏,请将其记录为警告。但是,当Grails验证失败(没有日志!)并且使程序员失明时,这不幸发生,对于那些不知道这一点的新手来说真的很难。最有经验的人只是说'这很容易调整',但这只是一种恶毒而不是更好的方式。

  

为了这个缘故,这些GORM Leaky Abstraction是唯一的抱怨我   曾经和Grails在一起。现在他们刚刚使用了这个配置参数。

答案 2 :(得分:0)

Peter Ledbrook关于GORM的一系列精彩文章:

虽然我不同意他关于Hibernate session flush的功能。他说“刷新:真正迫使Hibernate立即将所有更改保留在数据库中”。嗯,这只会发生在非事务性上下文中,因为当您在事务中时,从Hibernate会话中刷新的#SQL语句将在事务性RDBMS的回滚段中执行。因此,在交易提交之前,它们不会被持久化。

在事务中执行其他非数据库相关操作(如发送确认电子邮件)时,您想知道在验证中未明确声明的任何约束或数据库运行时错误是否已发生,例如,发送了确认电子邮件。

我的建议是autoFlush(grails.gorm.autoFlush = true)策略本身并没有错。您必须在开始时做出关于是否要使用它的技术决定,因此开发人员可以相应地编写代码,因为他们将知道是否必须明确执行刷新,或者Hibernate将在最后为他们执行此操作。你的交易方法。

要考虑的另一个常见用例是您是否要使用GORM执行批处理操作。如果你没有在任何数量的SQL操作中刷新Hibernate会话,那么你将遇到问题。