lunedì 31 gennaio 2011

Shared NamedQueries

I often find myself repeating the same namedQuery pattern in my domain classes. For example, I recently had the need of defining a lot of domain classes with the following structure


class Dummy {
String foo
Date validFrom
Date validTo

static constraints = {
}
}

where the two properties validFrom and validTo represent the time interval in which the object is valid.
For every such class I define the valid() namedQuery in order to fetch all the valid instances to date


static namedQueries = {
valid {
def now = new Date()
lt 'validFrom', now
gt 'validTo', now
}
}

Obviously, this solution is not very DRY, since the same query is spread over all my classes.
So, I decided to refactor my code a little and I came up with a much cleaner solution (I suspect I could do better, but I'm quite satisifed with that).
I define a QueryHolder class like that


class QueryHolder {

static def nowInRange(fromField, toField) {
{it ->
def now = new Date()
lt fromField, now
gt toField, now
}
}
}

It simply declares a static method that returns a closure to plug in the namedQuery structure.
The two parameters fromField and toField make the method flexible enough to be reused across classes which declares slightly different member field to track their validity.


static namedQueries = {
valid(QueryHolder.nowInRange('validFrom', 'validTo'))
}

Now, I can invoke valid() on my Dummy class to obtain all valid Dummies to date :)


def result = Dummy.valid().list()

Here's the complete Dummy listing


class Dummy {
String foo
Date validFrom
Date validTo

static constraints = {
}

static namedQueries = {
valid(QueryHolder.nowInRange('validFrom', 'validTo'))
}
}

class QueryHolder {

static def nowInRange(fromField, toField) {
{it ->
def now = new Date()
lt fromField, now
gt toField, now
}
}
}

Nessun commento:

Posta un commento