Default Declarative Transactions
Services are typically involved with co-ordinating logic between
domain classes, and hence often involved with persistence that spans large operations. Given the nature of services they frequently require transactional behaviour. You can of course use programmatic transactions with the
withTransaction method, however this is repetitive and doesn't fully leverage the power of Spring's underlying transaction abstraction.
Services allow the enablement of transaction demarcation, which is essentially a declarative way of saying all methods within this service are to be made transactional. All services have transaction demarcation enabled by default - to disable it, simply set the
transactional
property to
false
:
class CountryService {
static transactional = false
}
You may also set this property to
true
in case the default changes in the future, or simply to make it clear that the service is intentionally transactional.
Warning: dependency injection is the only way that declarative transactions work. You will not get a transactional service if you use the new
operator such as new BookService()
The result is all methods are wrapped in a transaction and automatic rollback occurs if an exception is thrown in the body of one of the methods. The propagation level of the transaction is by default set to
PROPAGATION_REQUIRED.
Custom Transaction Configuration
Grails also fully supports Spring's
Transactional
annotation for cases where you need more fine-grained control over transactions at a per-method level or need specify an alternative propagation level:
import org.springframework.transaction.annotation.*class BookService { @Transactional(readOnly = true)
def listBooks() { Book.list() } @Transactional def updateBook() {
// …
}}
For more information refer to the section of the Spring user guide on
Using @Transactional.
Unlike Spring you do not need any prior configuration to use Transactional
, just specify the annotation as needed and Grails will pick them up automatically.