Differences between the Grails @Transactional vs. the Spring @Transactional annotations

I would like to address this comment "However, in 2.3 the team felt it was a good idea (I disagree personally) to introduce a new annotation which could be applied not only to Services but also to Controllers.”

It was never the primary intention of the Grails team to introduce an annotation that could be used on both controllers and services. Our primary intention was to introduce an AST transform that eliminated the need for a proxy and performed better than Spring’s @Transactional. Grails’ @Transactional wires the necessary logic for dealing with transactions directly into the byte code and doesn’t need a proxy hence why we feel it is better than Spring’s version.

The fact that it also works on controllers is merely a side effect of the above that we discovered. Having said that in our experience too many Grails users do not correctly demarcate their transactional boundaries when using controllers. If you mark a controller action as being read-only then Hibernate does not need to perform dirty checking for any queries you do within the scope the action. This greatly improves performance of Grails applications and can very much be a good thing.

We absolutely encourage separation of logic into services, but if you consider the following trivial example:

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

It is overkill to introduce a service for such a trivial action, but if you don’t demarcate the query with a read-only transaction then Hibernate performs a dirty check on the instance which hurts performance.

Update 22/02/16: As of Grails 3.1 the Spring version is considered deprecated and is disabled by default (you can still re-enable if necessary)


Another difference with the Grails 2.3 version of the annotation is if you call method B from method A on the same service, the transactional attribute on method B will be honored. With the Spring annotation it will not be honored because you bypass the dynamic proxy where transactions are applied.

def methodA() {
    methodB()
}

@Transactional
def methodB() {
    ...
}

Prior to 2.3 the Spring annotation was used because it was applied to Services. Which are just simple Spring beans. However, in 2.3 the team felt it was a good idea (I disagree personally) to introduce a new annotation which could be applied not only to Services but also to Controllers. The difference is that the Grails 2.3 version of the annotation does a lot of AST transformation magic to work within the concept of a Grails controller.

Hope that helps.

Update

Functionally speaking, when applied to Services the Grails verson of the annotation is identical to the Spring version. Though it's slightly more efficient since it's an AST transformation applied to your code at compile time and not a proxy applied at runtime.