Tuesday, 14 June 2011

Two nice Groovy design patterns

Putting my deep SQL and HSQL roots on hold I took advantage of Hibernate Criteria (via the excellent Groovy builder for super readable code) to safely generate a dynamic query today. I stumbled into two problems:
  1. how to keep things DRY - can I avoid rewriting the same query multiple times when simple things change?
  2. how can I elegantly query associations whose names I do not know in advance?
I was able to resolve both issues quite satisfactory.

Keeping queries DRY

My first attempt was to create a basic query structure as a Groovy closure and then modify it at runtime as the exact query would be known. Couldn't make it work. Fortunately, the second attempt was more successful: I used a simple factory pattern to create the closure dynamically before feeding it into the Criteria Builder:
def createQuery = { Boolean discriminate ->
	 return {
	 	 projections {
	 	 	 sum "property"
	 	 }
	 	 if (discriminate) {
	 	 	 idEq 42
	 	 }
	 }
}
MyClass.createCriteria().list(createQuery(false))

Choosing associations dynamically

In order to reference an association, you have to use its name in the closure as a method call with a closure as the parameter. Suppose you have the name of the property in a string object, how do you call it as a method in the closure ? Using evals could've worked, but that would present a serious security risk. Groovy's GStrings to the rescue:
def discriminateProp = params.prop
def discriminateBy = params.val
def createQuery = { Boolean discriminate ->
	 return {
	 	 projections {
	 	 	 sum "property"
	 	 }
	 	 if (discriminate) {
	 	 	 "${discriminateProp}" {
	 	 	 	 	 idEq discriminateBy.toLong()
	 	 	 }
	 	 }
	 }
}
MyClass.createCriteria().list(createQuery(true))
I still have to wrap my brains around possible security risks of this approach, but at the first glance it seems solid.

No comments:

Post a Comment