2011-12-02 51 views
8

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

  1. 如果服务被配置为与静态事务=真,将它冲洗任何方法之后的每一个数据变化到DB与对象是脏并且被锁定在休眠会话调用?

  2. 我可以在课程级别使用@Transactional注释而不是static transactional = true吗?是否可以将@Transactional(readOnly = true)放在我希望他们从DB读取(查询,查找)数据的某些方法中?

  3. 交易继承如何?我的意思是,如果父服务配置为static transactional = true,并且子服务拥有它自己的@Transactional注释(在类上)以及某些@Transactional(readOnly = true)(在某些方法上),如果我从子对象调用父对象的方法会发生什么?

  4. 是否与抽象服务进行交易?因为据我所知,在抽象服务中,我们无法初始化其bean,也可能在启动应用程序时,Grails上下文中存在一些差异。

回答

7

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

对于问题#1,是 - 春/ 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

+0

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