关于 Grails 服务的一些问题

Posted

技术标签:

【中文标题】关于 Grails 服务的一些问题【英文标题】:Some questions about Grails service 【发布时间】:2012-01-11 04:46:00 【问题描述】:

我正在使用 Grails Web 应用程序,在使用 Grails 服务时遇到了很多奇怪的事情。所以我想问一些关于这个的问题,让我更多地了解 Grails 服务。这对我非常有帮助(也许对其他人也有帮助^_^)。提前致谢。

    如果服务配置为 static transactional = true,它是否会在使用脏对象调用并在 Hibernate 会话中锁定的任何方法后将每个数据更改刷新到 DB?

    我可以在类级别使用@Transactional 注释而不是static transactional = true 吗?是否可以将@Transactional(readOnly = true) 放在我只想让他们从数据库中读取(查询、查找)数据的某些方法中?

    事务继承如何?我的意思是,如果父服务配置为static transactional = true,并且子服务有自己的@Transactional 注释(在类上)和一些@Transactional(readOnly = true)(在某些方法上),如果我在父级调用方法会发生什么从孩子一个?

    事务性是否适用于抽象服务?因为据我所知,使用抽象服务我们无法初始化其 bean,并且可能在启动应用程序时,Grails 上下文存在一些差异。

【问题讨论】:

【参考方案1】:

每个问题你应该问一个问题:)

对于问题 #1,是的 - Spring/Hibernate 集成确保在提交之前发生刷新。因此,对save()delete() 的调用将被刷新,无需添加flush: true。此外,除非您调用 discard(),否则您尚未调用 save() 的脏实例也将被刷新。

对于#2:默认情况下服务是事务性的,所以transactional = true 实际上是多余的——你只需要将它指定为transactional = false。但是只有在没有@Transactional 注释的情况下才会创建自动事务包装器。如果您有一个或多个注释,那么这些注释定义了事务分界。所以默认情况下(即没有注释,也没有transactional 属性或transactional = true)所有方法都是事务性的,但如果您只注释方法的子集,那么只有那些方法是事务性的。

通常,当您想要非默认行为时,您会使用注释,即自定义传播、隔离、超时等(或像您的示例一样将其设为只读)。

您可以在类级别进行注释以使所有方法具有相同的配置,并且可以选择注释单个方法以覆盖类范围的默认值。

对于#3 和#4,适用标准规则(参见#2)。如果子类有注解,那么来自该类或父类的transactional = true 将被忽略,因为通过使用注解您已经告诉 Grails 您正在自己配置事物。

由于无法实例化抽象服务,实际实例化的具体子类将结合基类和自身的行为。如果一切都是transactional = true,那很简单,如果你有任何注释,那么它们就定义了规则。

调用超类中的方法就像调用当前类中的方法一样。但是,如果您没有考虑 Spring 代理方法的含义,那么这种行为有点违反直觉。当您调用事务方法时,代理会拦截调用并加入活动事务,或者在需要时启动一个新事务,或者在指定 REQUIRES_NEW 时启动一个新事务。但是一旦你进入真正的类并调用另一个方法,你就会绕过代理。因此,如果您使用不同的注释设置调用另一个方法,它们将被忽略。如果您打算这样做,请参阅此邮件列表讨论,了解正在发生的事情以及如何使用它:http://grails.1312388.n4.nabble.com/non-transactional-service-extends-transactional-service-outcome-td3619420.html

【讨论】:

太棒了!非常感谢您的明确回答。但是让我们从反面看一下第 3 点:父服务 A 在类级别标记为 @Annotation,A 中的方法 doParent() 为 readOnly=true,而子服务 B 没有任何关于事务的特定配置。为什么我从 B 调用 doParent(),尽管我强制它只读,它仍然刷新数据?

以上是关于关于 Grails 服务的一些问题的主要内容,如果未能解决你的问题,请参考以下文章

Grails 3 - 资源插件

环境特定的 Grails 服务配置

如何在 Grails 中动态选择服务

如何在 Grails 服务上调用初始化函数?

如何模拟闭包以测试 Grails 服务结果?

@PostConstruct 在 Grails 服务上静默失败