Showing posts with label sql. Show all posts
Showing posts with label sql. Show all posts

Sunday, May 3, 2009

Set pojo properties with groovy sql row results

This is probably documented somewhere that you can do this with a Map and a regular typed Object, I just hadn't run across it and tried it to see what happens.

You can just pass in a Map of properties to an Object and as long as you don't have any properties in your Map that are not defined in the class, it'll work fine. As an example:


class Person {
String name
Integer age
String address
}

def map = [ name: "Joe", age: 4, address: "Somewhere"]

Person p = new Person(map)

println "Peson name: $p.name, address: $p.address"


This comes in real handy when want you want to populate some groovy sql results into a collection of typed objects. As an example:


def getPersons() {
def persons = []
sql.eachRow("Select * from Person") {
persons << new Person( it.toRowResult() )
}
return persons
}

Monday, April 6, 2009

Using Groovy @Delegate

Groovy 1.6 introduces some killer stuff!

I really like @Delegate.

For those that don't use Groovy much, what @Delegate does is best seen by an example. The one in the link above is pretty good dealing with Date in an Event, but as a real world example here's how I needed it....

groovy.sql is pretty cool and you can call toRowResult() on each groovy result set object, which lets you use those GroovyRowResult objects directly calling the column name as properties... for example..


def sql = Sql.newInstance("jdbc:jtds:sybase://.....I", "user", "passr", "net.sourceforge.jtds.jdbc.Driver")
def results = []
sql.eachRow("SELECT firstName, lastName FROM Person") {
results << it.toRowResult()
}


//print first and last names from results collected:
results.each {
println "firstName = $it.firstName lastName= $it.lastName"
}


Ok simple enough, but now what if you wanted to also get a "fullName" property? Ok simple enough we'll just make a Person object and create a method to create it. But wait, I still need access to all those other database fields. Now sure in many CRUD apps you'd already have a Person object with all the typical fields firstName, lastName etc... but in this case I only need display data and I'm perfectly happy with using the database field names for the property names so I want to just use my groovyRowResult directly but also want to be able to call "lastNam.". So in Java what would one do? I don't want to mess around trying to extend GroovyRowResult (if I even could?) or maybe my Person also needed to already extend another Base object as it is. Obviously you want to wrap row in an adapter and then in Java you'd have to use some reflection and proxy method/property calls to the wrapped row object if a call to a method/property wasn't found in Person. Sort of a pain to have to code that proxy stuff though. Granted not difficult and you can cut and paste it from other projects once you've done it once, but with Groovy it's even easier and much cleaner. for my sql example above...


class Person {
@Delegate(interfaces=false) GroovyRowResult row

def getFullName() {
return "${row.firstName} ${row.lastName}"
}
}

//...
sql.eachRow("SELECT firstName, lastName FROM Person") {
results << new Person( row: it.toRowResult() )
}

results.each {
println "firstName = $it.firstName" // finds firstName in delegate!!!!
println "lastName = $it.lastName"
}


Before using Delegate I was using propertyMissing, which would be fine in this case since I only have one delegate but things would be trickier if I had multiple nested objects (whereas using @Delegate it wouldn't be an issue - assuming you didn't have conflicting method/property names - in which case not sure what would happen.) Even using the old propertMissing in Groovy is quite cool:


//using propertyMissing
class Person {
@Delegate GroovyRowResult row

def getFullName() {
return "${row.firstName} ${row.lastName}"
}

def propertyMissing(String prop) {
def result = row."${prop}"
}
}

Blogger Syntax Highliter