16

好吧,Grails声明式事务中有一点。它说:

grails.transaction.Transactional 注解最早是在 Grails 2.3 中引入的。在 2.3 之前,使用了 Spring 的 @Transactional 注解。

但我似乎无法找出这两个注释之间的主要区别是什么。为什么在以后的版本中没有使用 Spring 的注解?

4

6 回答 6

30

我想解决这个评论“但是,在 2.3 中,团队认为引入一个新注释是一个好主意(我个人不同意),它不仅可以应用于服务,还可以应用于控制器。”</p>

引入可用于控制器和服务的注解从来不是 Grails 团队的主要意图。我们的主要目的是引入一个 AST 转换,它消除了对代理的需求,并且比 Spring 的 @Transactional 性能更好。Grails 的 @Transactional 将处理事务的必要逻辑直接连接到字节码中,并且不需要代理,因此我们觉得它比 Spring 的版本更好。

它也适用于控制器的事实仅仅是我们发现的上述情况的副作用。话虽如此,根据我们的经验,太多的 Grails 用户在使用控制器时没有正确划分他们的事务边界。如果您将控制器操作标记为只读,则 Hibernate 不需要对您在该操作范围内执行的任何查询执行脏检查。这极大地提高了 Grails 应用程序的性能,并且可能是一件好事。

我们绝对鼓励将逻辑分离到服务中,但是如果您考虑以下简单的示例:

  @Transactional(readOnly=true)
  def show(Long id) {
       respond Foo.get(id)
  }

为这种微不足道的操作引入服务是过大的,但如果您不使用只读事务划分查询,那么 Hibernate 会对实例执行脏检查,这会损害性能。

22/02/16 更新:从 Grails 3.1 开始,Spring 版本被认为已弃用,默认情况下被禁用(如果需要,您仍然可以重新启用)

于 2014-05-13T11:55:17.913 回答
16

与 Grails 2.3 版本的注释的另一个区别是,如果您从同一服务上的方法 A 调用方法 B,则方法 B 上的事务属性将被兑现。使用 Spring 注释,它不会被兑现,因为您绕过了应用事务的动态代理。

def methodA() {
    methodB()
}

@Transactional
def methodB() {
    ...
}
于 2014-05-14T11:00:03.093 回答
5

在 2.3 之前,使用 Spring 注释是因为它应用于服务。这只是简单的 Spring bean。然而,在 2.3 中,团队认为引入一个新的注释是一个好主意(我个人不同意),它不仅可以应用于服务,还可以应用于控制器。不同之处在于 Grails 2.3 版本的注解在 Grails 控制器的概念中做了很多 AST 转换魔法。

希望有帮助。

更新

从功能上讲,当应用于服务时,注释的 Grails 版本与 Spring 版本相同。虽然它的效率稍高一些,因为它是在编译时应用于您的代码的 AST 转换,而不是在运行时应用的代理。

于 2014-05-13T10:13:21.073 回答
3

为什么在以后的版本中没有使用 spring 的注解?

您仍然可以使用 Spring 注释。Grails 版本更灵活,性能更高,因为我们可以在编译时构建很多逻辑,但 Spring 版本仍然存在,并且仍然像以前一样运行。

于 2014-05-13T10:40:16.150 回答
1

@PrakashJoshi 说:

因此,当您从操作调用服务方法时会发生什么,而该操作又具有其他事务属性。它是否被被调用方法的事务行为覆盖???

这取决于您将事务传播行为设置为什么(可在注释上设置)。PROPAGATION_REQUIRED(默认)将继续一个现有的,但 PROPAGATION_NEW 将启动一个新的,暂停当前的。

于 2015-09-04T09:40:22.153 回答
0

你仍然可以使用 spring 注解,但是 grails 版本更快并且更了解框架。

我强烈建议您使用 grails 版本。

于 2014-05-14T11:24:31.530 回答