7.4.4 Detached Criteria - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari
Version: 3.1.7
7.4.4 Detached Criteria
Detached Criteria are criteria queries that are not associated with any given database session/connection. Supported since Grails 2.0, Detached Criteria queries have many uses including allowing you to create common reusable criteria queries, execute subqueries and execute batch updates/deletes.Building Detached Criteria Queries
The primary point of entry for using the Detached Criteria is thegrails.gorm.DetachedCriteria
class which accepts a domain class as the only argument to its constructor:import grails.gorm.* … def criteria = new DetachedCriteria(Person)
build
method:def criteria = new DetachedCriteria(Person).build {
eq 'lastName', 'Simpson'
}
DetachedCriteria
instance do not mutate the original object but instead return a new query. In other words, you have to use the return value of the build
method to obtain the mutated criteria object:def criteria = new DetachedCriteria(Person).build {
eq 'lastName', 'Simpson'
}
def bartQuery = criteria.build {
eq 'firstName', 'Bart'
}
Executing Detached Criteria Queries
Unlike regular criteria, Detached Criteria are lazy, in that no query is executed at the point of definition. Once a Detached Criteria query has been constructed then there are a number of useful query methods which are summarized in the table below:Method | Description |
---|---|
list | List all matching entities |
get | Return a single matching result |
count | Count all matching records |
exists | Return true if any matching records exist |
deleteAll | Delete all matching records |
updateAll(Map) | Update all matching records with the given properties |
firstName
property:def criteria = new DetachedCriteria(Person).build { eq 'lastName', 'Simpson' } def results = criteria.list(max:4, sort:"firstName")
def results = criteria.list(max:4, sort:"firstName") {
gt 'age', 30
}
get
or find
methods (which are synonyms):Person p = criteria.find() // or criteria.get()
DetachedCriteria
class itself also implements the Iterable
interface which means that it can be treated like a list:def criteria = new DetachedCriteria(Person).build {
eq 'lastName', 'Simpson'
}
criteria.each {
println it.firstName
}
each
method is called. The same applies to all other Groovy collection iteration methods.You can also execute dynamic finders on DetachedCriteria
just like on domain classes. For example:def criteria = new DetachedCriteria(Person).build { eq 'lastName', 'Simpson' } def bart = criteria.findByFirstName("Bart")
Using Detached Criteria for Subqueries
Within the context of a regular criteria query you can useDetachedCriteria
to execute subquery. For example if you want to find all people who are older than the average age the following query will accomplish that:def results = Person.withCriteria { gt "age", new DetachedCriteria(Person).build { projections { avg "age" } } order "firstName" }
Person
) and hence the query can be shortened to:def results = Person.withCriteria { gt "age", { projections { avg "age" } } order "firstName" }
gtAll
query can be used:def results = Person.withCriteria { gtAll "age", { projections { property "age" } between 'age', 18, 65 } order "firstName" }
Method | Description |
---|---|
gtAll | greater than all subquery results |
geAll | greater than or equal to all subquery results |
ltAll | less than all subquery results |
leAll | less than or equal to all subquery results |
eqAll | equal to all subquery results |
neAll | not equal to all subquery results |
Batch Operations with Detached Criteria
TheDetachedCriteria
class can be used to execute batch operations such as batch updates and deletes. For example, the following query will update all people with the surname "Simpson" to have the surname "Bloggs":def criteria = new DetachedCriteria(Person).build { eq 'lastName', 'Simpson' } int total = criteria.updateAll(lastName:"Bloggs")
Note that one limitation with regards to batch operations is that join queries (queries that query associations) are not allowed within the DetachedCriteria
instance.
To batch delete records you can use the deleteAll
method:def criteria = new DetachedCriteria(Person).build { eq 'lastName', 'Simpson' } int total = criteria.deleteAll()