I've recently been looking at an 'interesting' project.
The original developer (whom I'm guessing was a PHP-ite in a former life) took Grails for a spin and on the whole did a pretty fair job of getting his application up and running and keeping the customer happy and so deserves a fair
amount of Kudos, not to mention Quatloos.
There was some 'grunge': a bit too much being done in GSP pages that should have been in controller code and not enough factoring into services, etc., but that's OK.
The application's domain handling was the one area that gave me pause to think, however.
There was a common pattern to it, which I'll try and explain…
The developer had used Grails' standard GORM domain classes to model the application's domain and (thus) initialize the database but throughout the various controllers I kept seeing code like
this:
def id = ...
def domainInstance = DomainClass.get(id)
def query = """
some 20-line query
walking the underlying relationships from DomainClassTable
to DomainClassTable to get at whatever was wanted
"""
def sql = sql.query(query)
sql.eachRow { r ->
}
The developer was using GORM quite trivially and for anything even slightly more 'demanding' he would "drop down" into plain SQL.
My first action was to groan out loud…
My second action was to slap my bright, shiny forehead…
My first thought was "Oh NO!" …
My second thought was "What a stupid developer"…
Then I calmed down a bit and reconsidered. I came to the conclusion that I was being a rather harsh: for those new to Grails and the Java platform it is not obvious just what GORM/Hibernate brings to the party.
Consider:
<?php
$username = "...";
$password = "...";
$hostname = "...";
$dbh = mysql_connect($hostname, $username, $password)
or die("Can't to connect to MySQL");
mysql_select_db("...",$dbh)
or die("Could not select database ...");
$result = mysql_query("SELECT * FROM table");
while ($row = mysql_fetch_array($result,MYSQL_ASSOC)) {
print "ID:".$row{'id'}.". ... ."<br>";
}
mysql_close($dbh);
?>
If this is what you have as your sole background and experience, and you are a busy guy with your nose to the grindstone (as we all tend to be), then a first read of the Grails documention (or the Hibernate or JPA documention for that
matter) wouldn't really show you about walking through associations and the joys of an SQL-free lifestyle.
This is sad, but it is also true.
(It's also sad but true that there are plenty of Java guys out there who don't look past plain 1999-era JDBC…and end up with similarly grungy stuff as a result.)
If you trawl through the Grails documentation (http://grails.org/do … .x/guide/single.html) you'll see that there's a fair bit in there about declaring associations,
establishing cascading saves, updates and deletes, etc. but very little on actually using these associations.
The Grails documentation (Section 5.2.1.2 "One-to-many") does show a very small example, but blink and you'll miss it!
So here goes my attempt at leading you to a SQL-free nirvana…
As is my wont, I'll talk through a trivial example application. In this case, its a school, with classes, students, teachers, rooms and books.
It has a very simple Object Model:

Note that I talk about an Object Model. As a developer, I am interested in the relationships between Objects. I am not interested in the underlying persistence mechanism's representation of that model (I'm guessing
that there are a few join tables in there, but that's just 'noise' that threatens to drown out what I want to think about). The Entity-Relationship diagram doesn't hold much interest for me.
Given my interest in all things Object, here are a couple of the more interesting domain classes:
package school
class Student {
String name
List books
static hasMany = [ books: school.Book ]
}
package school
class Book {
String title
}
package school
class School {
String name
List classes
static hasMany = [ classes: Class ]
}
Note that I have chosen to use Lists (rather than Sets, which is the default) to model the associations between my domain classes. This is often A Good Thing because it allows me to explicitly index into these associations, as will soon
become apparent.
Here's the first example of walking through various Object association:
School.findByName("Grails High").classes[0].students[0].books[0].title
I'll bet that you can easily determine what that line does.
Easily.
Quickly.
Think about that.
Especially if you are a SQL-head.
If you have persisted with plain SQL (pun intended), you'll know that there's a fair bit of walking through join tables, projecting and so on happening here.
I can guarantee you that a solution using the appropriate SQL wouldn't be so easily comprehensible (so "close to the problem definition") as what is shown above.
<RANT>
I also feel confident in pointing out that the solution you are now sketching out in your head is probably non-portable between databases and most likely not portable between different schema representations of the same basic Object
Model.
Ah..what the hell, I'll say it…what you were thinking was just plain wrong!
It probably/possibly would have correctly done data retrieval under some conditions, but I'll bet that you weren't thinking about the same schema, vendor-specific SQL dialect, etc. as I was.
Hence my statement.
In contrast, there's not too much of this ambiguity in the GORM version…
This is probably a whole other argument for another time, however.
</RANT>
Here's a neat second example:

The GSP that hits the database and navigates the inter-Object associations is clear, concise and "all business." It's outcome-focused, not heavily weighted to the mechanism of data retrieval:
<%@ page import="school.*" %>
<html>
<head>
<title>Welcome to Bob's GORMy School</title>
<style type="text/css" media="screen">
[...elided...]
</style>
</head>
<body>
<h1>Welcome to Bob's GORMy School</h1>
<%
def school = School.get(1)
def mkp = new groovy.xml.MarkupBuilder(out)
mkp.div([class: "homePagePanel"]) {
p school.name
school.classes.each {c ->
h2 ([style:'background:lightGray; font-weight: bold;'], "${c.code}: ${c.subject}")
p "Teacher: ${c.teacher.name}"
p "Room: ${c.room.designation}"
p "Students (${c.students.size()}):"
ul {
c.students.each {s ->
li s.name
p "Books (${s.books.size()}):"
ul {
s.books.each { b ->
li b.title
}
}
}
}
}
}
%>
</body>
</html>
The code and the solution are pretty clearly matched, so I'm guessing that once again you'll be able to work out what is going on…even if you don't know GORM or GSPs.
Pay particular attention to the ease with which the code can walk through associations between objects and also deal with the various cardinalities of the association.
(While you're at it, give praise to MarkupBuilder!)
Still not convinced, eh?
Oh well…take a week off and work on the equivalent SQL. Then take a further week off to recreate the simple page I show above using the resultant data in all it's stream-y, batch-oriented weirdness. I'll wait…
Let's do some comparison shopping.
The following code snippets are equivalent ways of undertaking the business operation "for each student, find all the titles of all their books":
println "GORM:"
Student.findAll().each { s ->
s.books.each { b ->
println "${s.name}: ${b.title}"
}
}
println "SQL:"
def sql = new Sql(dataSource)
def qry = """
select s.name, b.title
from Student s
inner join Student_Book sb on s.id = sb.student_books_id
inner join Book b on sb.book_id = b.id
"""
sql.eachRow(qry) {
println "${it.name}: ${it.title}"
}
Which more clearly matches the expected business operation?
Life is all about change, so try changing things ever so slightly:
println "GORM:"
Student.findAll().each { s ->
println s.name
s.books.each { b ->
println b.title
}
}
Trivial change, trivially easy with GORM.
I leave the equivalent change to the SQL morass as an exercise for the reader…
The drawback here is that your PHB may be tempted to change things around too often. There's probably a cure for that, however.
Go on…say it…be brave…it's a big issue.
Take a look here first.
Then I'll quote from Gavin King, the creator of Hibernate:
Note that I have not yet met a serious performance problem in Hibernate 2.x that I could not solve quite quickly.
(Note that we're a long way past the 2.x series now.)
You could argue that the developer of the application I am talking about was concerned with optimizing the application's performance. A laudable goal which we'll see about in a second…for now, just let me say that this application's
whole database is only about 250Mb. My mobile phone would give good performance serving this database, regardless of how I sub-optimally I were to structure the queries! I exaggerate (slightly) but its clear that there's a quick
"bang for buck" calculation to be made here, one that strongly argues against 'optimal' SQL.
Naive use of Hibernate (or any such tool) can lead to the n + 1 problem where a collection requires multiple queries to retrieve.
GORM tries to assist with this where it can, and makes it possible to tune the behaviour of an application for various situations. One of the most powerful tools for this is the ability to configure lazy/eager/batch fetching.
For example, if I look at the actual usage pattern of the association between Class and Student, I may conclude that it is appropriate to always eagerly fetch Student instances at the same time as a Class instance is
fetched from the database. I might provide a mapping for Class as follows:
package school
class Class {
String code
String subject
Teacher teacher
Room room
List students
static hasMany = [ students: Student ]
static mapping = {
students fetch:"join"
}
}
I may conclude that in some usage situations, the relationship between Student and Book is an eager one: all accesses to a Student instance involves looking at the associated list of Book instances.
println "GORM(eager):"
Student.findAll([fetch:[books: "eager"]]).each { s ->
println s.name
s.books.each { b ->
println b.title
}
}
You can peek around (p6spy is your friend) and see how the database is driven in this situation:
select
this_.id as id7_1_,
this_.version as version7_1_,
this_.name as name7_1_,
books2_.student_books_id as student1_3_,
book3_.id as book2_3_,
books2_.books_idx as books3_3_,
book3_.id as id0_0_,
book3_.version as version0_0_,
book3_.title as title0_0_
from
student this_
left outer join
student_book books2_
on this_.id=books2_.student_books_id
left outer join
book book3_
on books2_.book_id=book3_.id
No n + 1 problem here…
In other usage situations, a lazy approach may be appropriate:
println "GORM(lazy):"
Student.findAll([fetch:[books: "lazy"]]).each { s ->
println s.name
}
This gives pretty simple and effective SQL:
select
this_.id as id7_0_,
this_.version as version7_0_,
this_.name as name7_0_
from
student this_
Even in those situations where "only SQL will do", GORM allows the use of HQL to "get closer to the metal" while still avoiding a lot of drudgery:
Book.executeQuery("select b from Book as b, Student as s where (s.id=:st) and (b in elements(s.books))",
[st: 2L]).each { println it.title }
Of course, you could do it the hard way:
select
book0_.id as id2_,
book0_.version as version2_,
book0_.title as title2_
from
book book0_,
student student1_
where
student1_.id=?
and (
book0_.id in (
select
books2_.book_id
from
student_book books2_
where
student1_.id=books2_.student_books_id
)
)
How obscure is that! There's nothing in that mess that tells me what business needs I am trying to meet. It's the database equivalent of "assembly language" and-just like all assembly languages-is best left to tools
that know what they are doing.
It's good to have choice.
Really.
With GORM, I have a situation where I can start off simply and get progressively more sophisticated as the proven demands of my application require. I can build an Object Model for a domain without worrying about mechanics of what magic
incantations I will need to make it work. I have a "tuning point" in my application that I can work with. This is All Good Stuff.
Object graph navigation is extremely powerful, so go out and practice. You may have to play with it a bit before it gets under your skin but you'll be far more productive as a result.
I've seen a system convert from GORM-style to plain SQL data access (driven by a manager's "SQL experience") "in the name of performance" only to find the resulting true performance drop through the floor. GORM/Hibernate does a lot of
smart things that an average programmer just won't ever "get around to."
I'm really only touching the surface of things here (I haven't even talked about GORM's wonderful second-level
cache, but I hope that all this helps.
Here's a nice starter resource for Hibernate, the technology underlying GORM: Hibernate: A Developer's Notebook. Its a good read, even if its not GORM-specific.