Skip to main content

Session Notes - A Practical Take on GORM

Presenter: Robert Fischer
Author: Grails Persistence with GORM and GSQL
SmokeJumperIT -- Grails consulting and training


  • Overview of GORM

  • Intro to HQL

  • tour of GORM labs

  • tour of GORM plugins

  • extending GORM

GORM 101

  • Grails Object Relational Mapping

  • extensible and dynamic data access API

    • dynamic -- as you describe to grails what's in your application, you get more functionality automatically

  • hibernate wrapper (sometimes)

    • can use GORM outside of grails

    • transaction handling

    • data cache

    • schema generation/update system

  • even with the no SQL movement you still need an object to something mapping

Basic GORM Conventions

  • ./grails-app/domain

  • domain classes define tables

  • instance properties define columns

  • static properties define configuration

    • e.g. static hasMany = [bazzes:Baz], static mapping = { ... }

    • any time you see this, some sort of Grails magic is going to be happening behind the scenes

  • automatic id and version

    • GORM assumes you want an artificial ID and you want to work with optimistic locking

    • natural keys are enticing, but always become a problem

    • can opt out of these, but not encouraged

  • opt-in timestamping using dateCreated and lastUpdated

  • everything beyond these basics is probably boundary conditions or a need to extend GORM in some way

GORM Classes (Domain Classes)

  • even with a simple class Baz {} declaration you get tons of functionality

  • better to err on the side of having a domain class for everything in your app to get counts, lists, findByVersion, etc.

  • constraints used for data integrity

    • note that if you're using existing data you can pull "bad" data back but when you try to save, the constraints will kick in and fail so you'll have to deal with the bad data at that point

  • mapping -- depending on how you define things may or may not get mapped

    • String foo (declared string) = mapped

    • bar (only defined via its getter and setter but not declared) = mapped

      • this will always be dirty

      • can come in handy for implementing transforms in an overridden setter

    • bar2 (default artificial property) = not mapped

      • can come in handy for tracking schema changes over time without having this reflected in the database

    • foo2 (default natural property) = not mapped

      • the default part is the problem, not artificial vs. natural

    • baz (runtime added property) = not mapped

      • at application startup grails looks at the compiled structure of the classes to generate hibernate mappings

Underappreciated Methods

  • Foo.lock(id)

    • pulls an object back and locks it from being updated from other processes

    • can solve transactional issues

    • does for update in oracle, currently does nothing in mysql (but supposedly this is getting implemented)


    • pulls a record from the database and says "I'm not going to modify this"

    • if changes are made on the object after read, they're ignored

    • saves cache since it won't be cached

  • Foo.findAllWhere(bar:'one',baz:true)

    • can be implemented as Foo.findAllByBarAndBaz('one', true) but is more concise

  • Foo.executeQuery(hql) and Foo.executeUpdate(hql)

    • can use executeUpdate on update, delete, insert

    • allows you to take a bit more ownership of what's going on with the database and the generated sql

Hibernate Query Language (HQL)

  • like SQL but with a lot less pain

    • working directly with objects and relationships as opposed to having to write sql joins manually

    • if you're finding yourself writing sql and manually building up objects, chances are hql can handle what you're doing more simply

  • leverages mapped classes and properties

  • provides abilities to construct objects and maps directly in queries

  • one major limitation: error reporting is miserable

    • if you screw up your hql statement in a way that makes sense to the parser, error messages are good

    • if the hql doesn't make sense to the parser, you just get a null pointer exception from somewhere deep in hibernate

    • hibernate team is aware of this and working on improving

HQL for SQL-heads

  • query on objects, not on database tables

  • objects are normally returned

  • select * can be left off (just "from Foo")

  • no need to join *-to-one relationships: from Foo f where = ?

  • traverse many-to-many relationships via a joining on object relationships

    • from Foo f join f.bazzes b

    • can say "fetch join" to eagerly pull back bazzes for Foo

  • on existing databases--can use GREG (or GRAG?) -- Grails Application Generator

    • generates domain classes, etc. from an existing database

    • falls down if some company mandates all db access is through storedprocs

      • problem for Hibernate in general

      • fighting against the GORM conventions so hard that it makes it very difficult

      • plugin available to specify different databases for different domain objects--can get around some of this going this route

HQL Tips and Tricks

  • encapsulate the HQL in methods

    • don't put it in a service--put it on the domain class where it belongs

    • HQL is referencing properties, so if the property name changes you have to track all references down if this isn't in the domain class

  • use $ to save having to write out package names

    • standard groovy references--resolves the same way

  • use simple interpolation (${}) to add a bit of dynamism to your query

  • do not ever directly interpolate external values into hql

    • sql injection attack vector

    • always pass these in as parameters


  • plugin

  • tons of added methods to GORM

    • Foo.query -- shorter reference for HQL queries

    • for any property on a class you get

      • min, max, avg, sum, count, countDistinct on each property (e.g. Foo.minBar, Foo.maxBar, etc.)

    • Foo.connection -- access to current db connection

    • Foo.sql

    • Foo.session

    • Foo.flush()

    • $foo.errors -- nicer representation of errors

    • Foo.withCriteria -- allows ordering by nested properties (only works for one to one properties)

    • Gorm.connection, Gorm.flush, etc.

      • makes calls directly on gorm without having to refer to an arbitrary domain class

    • transactional actions in controllers

      • got him flamed on the list since this is supposed to be in services, but many people do db stuff in controllers

    • HasMany pagination/counts
      foo.bars(max:2, offset:3)

    • session object dehydration

      • if an object is thrown into the http session and it has an id, the id gets persisted in the session and it can be used to pull back the domain class if the object is attempted to be retrieved after the hibernate session has died

Favorite GORM Stunt: Transparent API Switch

  • assume there is a slow gorm api call
    Foo.findAllByBarOrBaz(bar, baz)

  • define a static method with the api call method name and hand-optimized sql
    def ids = Foo.sql.rows(query)*.id

  • return the (possibly cached) instances
    return Foo.getAll(ids)

Other GORM Plugins

  • audit logging

    • automatically keeps an audit trail on database activity

  • extended GORM mappings

  • GORM HBase (Hadoop HBase)


    • exists because of Google App Engine and the BigTable JPA functionality

  • explicit insert

    • allows you to do an explicit insert as opposed to save() which might do an insert or an update

  • datasources (per-domain class data source)

  • multitenant (per-tenant data source)

    • tenant attached to an HTTP request

    • great for situations where you have multiple clients each of which has their own datasource

  • system itools

    • plugin for IBM itools

  • DTO

  • joda-time

    • makes Joda-Time compatible with java.util.Date

    • makes all Joda-Time structures persistable to the database

Extending GORM The Easy Way

  • create plugin based on GORM Labs
    dependsOn = [gormLabs: '0 > *']

    • lets you take advantage of high-level stuff that GORM labs fixes

  • do metaClass mangling in doWithDynamicMethods

  • retrieve domain class metaClasses by application.domainClasses*.clazz

Current FOSS Projects - Shameless Cry for Help

  • Liquibase-DSL / Autobase

  • Bitescript (was JVMScript)

  • GORM Labs, Testing Labs, Sublog

  • JConch


  • interesting plugins for other frameworks/languages

    • PHP plugin -- Grails can wrap existing PHP apps

  • any cases where you wouldn't use GORM/Hibernate?

    • if storedprocs are required, not a good fit

    • in pretty much every other case hibernate works well

    • spent some time doing rails, perfer gorm method of doing things as opposed to activerecord

  • in production databases, what's the best practice for the datasource setting? (e.g. create, update, create-drop, etc.)

    • schema management is a difficult problem if you want 100% uptime

    • changing from one schema to another can cause some issues with hibernate

    • autobase plugin fixes some of these problems -- allows you to run migrations but have to write migrations by hand at this point


Popular posts from this blog

Installing and Configuring NextPVR as a Replacement for Windows Media Center

If you follow me on Google+ you'll know I had a recent rant about Windows Media Center, which after running fine for about a year suddenly decided as of January 29 it was done downloading the program guide and by extension was therefore done recording any TV shows.

I'll spare you more ranting and simply say that none of the suggestions I got (which I appreciate!) worked, and rather than spending more time figuring out why, I decided to try something different.

NextPVR is an awesome free (as in beer, not as in freedom unfortunately ...) PVR application for Windows that with a little bit of tweaking handily replaced Windows Media Center. It can even download guide data, which is apparently something WMC no longer feels like doing.

Background I wound up going down this road in a rather circuitous way. My initial goal for the weekend project was to get Raspbmc running on one of my Raspberry Pis. The latest version of XBMC has PVR functionality so I was anxious to try that out as a …

Setting Up Django On a Raspberry Pi

This past weekend I finally got a chance to set up one of my two Raspberry Pis to use as a Django server so I thought I'd share the steps I went through both to save someone else attempting to do this some time as well as get any feedback in case there are different/better ways to do any of this.

I'm running this from my house (URL forthcoming once I get the real Django app finalized and put on the Raspberry Pi) using I don't cover that aspect of things in this post but I'm happy to write that up as well if people are interested.

General Comments and Assumptions

Using latest Raspbian “wheezy” distro as of 1/19/2013 (’lll be using Nginx ( as the web server/proxy and Gunicorn ( as the WSGI serverI used heavily as I was creating this, so many thanks to the author of that tutorial. If you’re looking for more details on …

The Definitive Guide to CouchDB Authentication and Security

With a bold title like that I suppose I should clarify a bit. I finally got frustrated enough with all the disparate and seemingly incomplete information on this topic to want to gather everything I know about this topic into a single place, both so I have it for my own reference but also in the hopes that it will help others.Since CouchDB is just an HTTP resource and can be secured at that level along the same lines as you'd secure any HTTP resource, I should also point out that I will not be covering things like putting a proxy in front of CouchDB, using SSL with CouchDB, or anything along those lines. This post is strictly limited to how authentication and security work within CouchDB itself.CouchDB security is powerful and granular but frankly it's also a bit quirky and counterintuitive. What I'm outlining here is my understanding of all of this after taking several runs at it, reading everything I could find on the Internet (yes, the whole Internet!), and a great deal…