SlideShare a Scribd company logo
Overview of GORM


     Chris Richardson
 Author of POJOs in Action
 www.chrisrichardson.net
About Chris
                            Grew up in England and live in Oakland, CA
                            Over 20+ years of software development
                            experience including 12 years of Java
                            Author of POJOs in Action
                            Speaker at JavaOne, SpringOne, NFJS,
                            JavaPolis, Spring Experience, etc.
                            Chair of the eBIG Java SIG in Oakland
                            (www.ebig.org)
                            Run the Groovy/Grails meetup
                            (http://java.meetup.com/161)
                            Run a consulting and training company that
                              u    co su t g a d t a     g co pa y t at
                            helps organizations build better software faster
                            and deploy it on Amazon EC2
                            Founder of Cloud Tools, an open-source project
                            for deploying Java applications on Amazon EC2:
                            http://code.google.com/p/cloudtools
                            http://code google com/p/cloudtools
                            Founder of a startup that provides outsourced,
                            automated, and Java-centric datacenter
                            management on the cloud:
                            www.cloudfoundry.com
                                              y



                                                                      Slide 2
          Copyright (c) 2009 Chris Richardson. All rights reserved.
What’s GORM?
 GORM = Grails Object Relational Mapping
 Built
 B ilt on Hibe nate
          Hibernate
   Leverages the power of Hibernate
   But is very different - simpler, easier to use API
             y                p,
 Uses convention over configuration
   Defaults for which classes to persist
   Defaults for their O/R mapping
 Leverages the meta-object protocol
   Adds persistence methods to domain classes
         p
   No equivalent of Hibernate Session
   Avoids the need for dependency injection
   Eliminates many DAO cookie-cutter methods

                                                                           Slide 3
               Copyright (c) 2009 Chris Richardson. All rights reserved.
Database access made easy
                        y
 class Customer {
    String name
         g
 }



 Customer c = new Customer(quot;John Doequot;)
 Ct               Ct      (quot;J h D quot;)

 if (!c.save())
    fail quot;validation failed: ${c.errors}quot;

 Customer c2 = Customer.get(c.id)
                                                                                    No dependency
                                                                                       injection

 c2.delete()

 assertNull Customer.get(c.id)


 def customers = Customer findAllByName(“Fred”)
                 Customer.findAllByName( Fred )


                                                                                    Slide 4
                        Copyright (c) 2009 Chris Richardson. All rights reserved.
Relationships don’t have to be
 difficult

class Customer {
   static hasMany = [ accounts : Account]
}

class Account {
   static belongsTo = [customer: Customer]
   double balance
}


 Customer c = <…>
 Account a = new Account(…)
 c.addToAccounts(a)

 assertSame c, a.customer
 assertTrue c.accounts.contains(a)




                                                                                     Slide 5
                         Copyright (c) 2009 Chris Richardson. All rights reserved.
When the defaults aren’t right
                            g
class Customer {
   static transients = [quot;networthquot;]
                       [          ]

    static mapping = {
      id column: 'customer_id'
      table 'crc_customer'
                _
      columns {
         name column: 'customer_name'
      }
    }


    def getNetworth() { …}
    …
}




                                                                                         Slide 6
                             Copyright (c) 2009 Chris Richardson. All rights reserved.
Working with constraints
       g
class Customer {

    static constraints = {
            name(size: 5..15, blank: false)
    }

    String name

}




             Checked by the UI
             Checked by save()
             Used by GORM to generate schema constraints




                                                                                      Slide 7
                          Copyright (c) 2009 Chris Richardson. All rights reserved.
More on dynamic finders
         y
 Rich query language
   Various methods: fi dB () fi dAllB ()
   Vi          th d findBy…(), findAllBy…(),
   countBy…()
   Various operators: e.g
   findAllByFirstNameAndLastName(…),
   findAllByBalanceLessThan(…),
   findAllByStatusIsNotNull()
           y               ()
 BUT:
   Limited to single class/table, i.e. no joins
   Lack of encapsulation – the name of the
   finder reflects the implementation – not the
   meaning

                                                                          Slide 8
              Copyright (c) 2009 Chris Richardson. All rights reserved.
When dynamic finders are
   insufficient

                                                                              HQL

List accounts = Account.findAll(“from Account where balance < ?”, [threshold])




  def c = Account.createCriteria()
  def results = c.list {
     lt( balance
     lt(“balance”, threshold)
  }




                                                                                        Slide 9
                            Copyright (c) 2009 Chris Richardson. All rights reserved.
Mapping with XML or annotations
  pp g
 Using .hbm.xml files
   Create grails-
   app/conf/hibernate/hibernate.cfg.xml
   Define .hbm.xml mapping files
   D fi    hb     l      i  fil
   Map either Groovy or Java classes
 Using JPA annotations
 Ui            t ti
   Annotate Java classes
   Create hib
   C      hibernate.cfg.xml
                     f    l
 You can still use the dynamically
 defined
 d fi d GORM methods i G
                    th d in Groovy
                                                                         Slide 10
             Copyright (c) 2009 Chris Richardson. All rights reserved.
Under the covers
 Creates DataSource specified in grails-
 app/config/DataSource.groovy
 Creates Hibernate SessionFactory
 Use ExpandoMetaClass mechanism
   Add persistence methods, e.g.
   domainClass.metaClass.'static'.get = {…}
   Adds methodMissing() to handle dynamic
   finders
   fi d
   These methods have a reference to the
   SessionFactory

                                                                        Slide 11
            Copyright (c) 2009 Chris Richardson. All rights reserved.
GORM is great but …
        g
 GORM does not support multiple
 DataSources
 Lack of SOC
   Data access logic is scattered around the
   application rather than being
   encapsulated by DAOs
 CoC-based mapping works best for
 new databases
 Disadvantages of programming in a
 dynamic language
                                                                         Slide 12
             Copyright (c) 2009 Chris Richardson. All rights reserved.
Further reading
              g
 My ACM Queue article:
   http://queue.acm.org/detail.cfm?id=1394140




                                                                           Slide 13
               Copyright (c) 2009 Chris Richardson. All rights reserved.

More Related Content

Overview of Grails Object Relational Mapping (GORM)

  • 1. Overview of GORM Chris Richardson Author of POJOs in Action www.chrisrichardson.net
  • 2. About Chris Grew up in England and live in Oakland, CA Over 20+ years of software development experience including 12 years of Java Author of POJOs in Action Speaker at JavaOne, SpringOne, NFJS, JavaPolis, Spring Experience, etc. Chair of the eBIG Java SIG in Oakland (www.ebig.org) Run the Groovy/Grails meetup (http://java.meetup.com/161) Run a consulting and training company that u co su t g a d t a g co pa y t at helps organizations build better software faster and deploy it on Amazon EC2 Founder of Cloud Tools, an open-source project for deploying Java applications on Amazon EC2: http://code.google.com/p/cloudtools http://code google com/p/cloudtools Founder of a startup that provides outsourced, automated, and Java-centric datacenter management on the cloud: www.cloudfoundry.com y Slide 2 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 3. What’s GORM? GORM = Grails Object Relational Mapping Built B ilt on Hibe nate Hibernate Leverages the power of Hibernate But is very different - simpler, easier to use API y p, Uses convention over configuration Defaults for which classes to persist Defaults for their O/R mapping Leverages the meta-object protocol Adds persistence methods to domain classes p No equivalent of Hibernate Session Avoids the need for dependency injection Eliminates many DAO cookie-cutter methods Slide 3 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 4. Database access made easy y class Customer { String name g } Customer c = new Customer(quot;John Doequot;) Ct Ct (quot;J h D quot;) if (!c.save()) fail quot;validation failed: ${c.errors}quot; Customer c2 = Customer.get(c.id) No dependency injection c2.delete() assertNull Customer.get(c.id) def customers = Customer findAllByName(“Fred”) Customer.findAllByName( Fred ) Slide 4 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 5. Relationships don’t have to be difficult class Customer { static hasMany = [ accounts : Account] } class Account { static belongsTo = [customer: Customer] double balance } Customer c = <…> Account a = new Account(…) c.addToAccounts(a) assertSame c, a.customer assertTrue c.accounts.contains(a) Slide 5 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 6. When the defaults aren’t right g class Customer { static transients = [quot;networthquot;] [ ] static mapping = { id column: 'customer_id' table 'crc_customer' _ columns { name column: 'customer_name' } } def getNetworth() { …} … } Slide 6 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 7. Working with constraints g class Customer { static constraints = { name(size: 5..15, blank: false) } String name } Checked by the UI Checked by save() Used by GORM to generate schema constraints Slide 7 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 8. More on dynamic finders y Rich query language Various methods: fi dB () fi dAllB () Vi th d findBy…(), findAllBy…(), countBy…() Various operators: e.g findAllByFirstNameAndLastName(…), findAllByBalanceLessThan(…), findAllByStatusIsNotNull() y () BUT: Limited to single class/table, i.e. no joins Lack of encapsulation – the name of the finder reflects the implementation – not the meaning Slide 8 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 9. When dynamic finders are insufficient HQL List accounts = Account.findAll(“from Account where balance < ?”, [threshold]) def c = Account.createCriteria() def results = c.list { lt( balance lt(“balance”, threshold) } Slide 9 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 10. Mapping with XML or annotations pp g Using .hbm.xml files Create grails- app/conf/hibernate/hibernate.cfg.xml Define .hbm.xml mapping files D fi hb l i fil Map either Groovy or Java classes Using JPA annotations Ui t ti Annotate Java classes Create hib C hibernate.cfg.xml f l You can still use the dynamically defined d fi d GORM methods i G th d in Groovy Slide 10 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 11. Under the covers Creates DataSource specified in grails- app/config/DataSource.groovy Creates Hibernate SessionFactory Use ExpandoMetaClass mechanism Add persistence methods, e.g. domainClass.metaClass.'static'.get = {…} Adds methodMissing() to handle dynamic finders fi d These methods have a reference to the SessionFactory Slide 11 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 12. GORM is great but … g GORM does not support multiple DataSources Lack of SOC Data access logic is scattered around the application rather than being encapsulated by DAOs CoC-based mapping works best for new databases Disadvantages of programming in a dynamic language Slide 12 Copyright (c) 2009 Chris Richardson. All rights reserved.
  • 13. Further reading g My ACM Queue article: http://queue.acm.org/detail.cfm?id=1394140 Slide 13 Copyright (c) 2009 Chris Richardson. All rights reserved.