GORM supports the concept of
dynamic finders. A dynamic finder looks like a static method invocation, but the methods themselves don't actually exist in any form at the code level.
Instead, a method is auto-magically generated using code synthesis at runtime, based on the properties of a given class. Take for example the
Book
class:
class Book {
String title
Date releaseDate
Author author
}
class Author {
String name
}
The
Book
class has properties such as
title
,
releaseDate
and
author
. These can be used by the
findBy and
findAllBy methods in the form of "method expressions":
def book = Book.findByTitle("The Stand")book = Book.findByTitleLike("Harry Pot%")book = Book.findByReleaseDateBetween( firstDate, secondDate )book = Book.findByReleaseDateGreaterThan( someDate )book = Book.findByTitleLikeOrReleaseDateLessThan( "%Something%", someDate )
Method Expressions
A method expression in GORM is made up of the prefix such as
findBy followed by an expression that combines one or more properties. The basic form is:
Book.findBy([Property][Comparator][Boolean Operator])?[Property][Comparator]
The tokens marked with a '?' are optional. Each comparator changes the nature of the query. For example:
def book = Book.findByTitle("The Stand")book = Book.findByTitleLike("Harry Pot%")
In the above example the first query is equivalent to equality whilst the latter, due to the
Like
comparator, is equivalent to a SQL
like
expression.
The possible comparators include:
InList
- In the list of given values
LessThan
- less than the given value
LessThanEquals
- less than or equal a give value
GreaterThan
- greater than a given value
GreaterThanEquals
- greater than or equal a given value
Like
- Equivalent to a SQL like expression
Ilike
- Similar to a Like
, except case insensitive
NotEqual
- Negates equality
Between
- Between two values (requires two arguments)
IsNotNull
- Not a null value (doesn't require an argument)
IsNull
- Is a null value (doesn't require an argument)
Notice that the last 3 require different numbers of method arguments compared to the rest, as demonstrated in the following example:
def now = new Date()
def lastWeek = now - 7
def book = Book.findByReleaseDateBetween( lastWeek, now )books = Book.findAllByReleaseDateIsNull()
books = Book.findAllByReleaseDateIsNotNull()
Boolean logic (AND/OR)
Method expressions can also use a boolean operator to combine two criteria:
def books =
Book.findAllByTitleLikeAndReleaseDateGreaterThan("%Java%", new Date()-30)
In this case we're using
And
in the middle of the query to make sure both conditions are satisfied, but you could equally use
Or
:
def books =
Book.findAllByTitleLikeOrReleaseDateGreaterThan("%Java%", new Date()-30)
At the moment, you can only use dynamic finders with a maximum of two criteria, i.e. the method name can only have one boolean operator. If you need to use more, you should consider using either
Criteria or the
HQL.
Querying Associations
Associations can also be used within queries:
def author = Author.findByName("Stephen King")def books = author ? Book.findAllByAuthor(author) : []
In this case if the
Author
instance is not null we use it in a query to obtain all the
Book
instances for the given
Author
.
Pagination & Sorting
The same pagination and sorting parameters available on the
list method can also be used with dynamic finders by supplying a map as the final parameter:
def books =
Book.findAllByTitleLike("Harry Pot%", [max:3,
offset:2,
sort:"title",
order:"desc"])