Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Advanced GORM - Beyond Relational

graemerocher
September 10, 2014

Advanced GORM - Beyond Relational

Talk by Graeme Rocher at SpringOne2GX 2014 on Advanced GORM

graemerocher

September 10, 2014
Tweet

More Decks by graemerocher

Other Decks in Programming

Transcript

  1. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Advanced GORM - Beyond Relational
    By Graeme Rocher

    View Slide

  2. Agenda
    § Understanding GORM Internals
    § GORM Standalone
    § Tips and Tricks
    § Jumping into MongoDB
    § Unit testing with GORM
    § Summary / Q & A

    View Slide

  3. GORM
    • Powerful multi-datastore
    query layer
    • Dynamic finders, criteria, and
    persistence methods
    • Integrated validation
    • Automatic mapping of entities
    to underlying datastore
    • Easy access to native APIs
    3

    View Slide

  4. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Understanding what makes GORM tick
    GORM Internals

    View Slide

  5. Grails Data Mapping Project
    • https://github.com/grails/grails-data-mapping
    5

    View Slide

  6. Built by Travis
    • https://travis-ci.org/grails/grails-data-mapping
    6

    View Slide

  7. Developer Documentation
    • http://grails.github.com/grails-data-mapping/
    7

    View Slide

  8. Important Subprojects
    • grails-datastore-core!
    – Core low level API
    • grails-datastore-gorm!
    – GORM API layer
    • grails-datastore-gorm-tck!
    – Test Suite
    8

    View Slide

  9. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Demo: Code Walkthrough

    View Slide

  10. Contribute to GORM
    • GORM is huge and sprawling
    • Covers loads of data stores
    • Great area to contribute to the
    community. Some ideas:
    • Multi Tenancy
    • Elastic Search
    • Hadoop / HBase
    10

    View Slide

  11. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Use GORM outside of Grails
    GORM Standalone

    View Slide

  12. What is GORM Standalone?
    • Easy initialisation of GORM outside of Grails
    • And a set of Spring Boot plugins
    • Required modularisation of codebase
    • Reduction of external dependencies
    • Simplification of GORM setup
    12

    View Slide

  13. Standalone Entities
    • Annotated with grails.persistence.Entity
    13
    @Entity  
    class  Person  {  
           String  name  
           static  constraints  =  {  
                   name  blank:false  
           }  
    }

    View Slide

  14. GORM for Hibernate Standalone
    • https://gist.github.com/graemerocher/c25ec929d9bcd1adcbea
    14
    @Grab("org.grails:grails-­‐datastore-­‐gorm-­‐hibernate4:3.1.2.RELEASE")  
    @Grab("com.h2database:h2:1.3.164")  
    !
    import  grails.orm.bootstrap.*  
    !
    init  =  new  HibernateDatastoreSpringInitializer(Person)  
    def  dataSource  =  new  DriverManagerDataSource(Driver.name,  
    "jdbc:h2:prodDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALS
    E",  'sa',  '')  
    init.configureForDataSource(dataSource)  

    View Slide

  15. GORM for MongoDB Standalone
    • https://gist.github.com/graemerocher/9683650
    15
    @Grab("org.grails:grails-­‐datastore-­‐gorm-­‐mongodb:3.0.2.RELEASE")  
    !
    import  grails.mongodb.bootstrap.*  
    !
    init  =  new  MongoDbDataStoreSpringInitializer(Person)  
    init.configure()

    View Slide

  16. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Demo: GORM Standalone

    View Slide

  17. GORM for Hibernate in Spring Boot
    • Add gorm-hibernate4-spring-boot as a dependency
    !
    !
    !
    !
    • Then add persistent entities that are annotated with 

    grails.persistence.Entity
    17
    compile  "org.grails:gorm-­‐hibernate4-­‐
    spring-­‐boot:1.0.0.RELEASE"

    View Slide

  18. GORM for MongoDB in Spring Boot
    • Add gorm-mongodb-spring-boot as a dependency
    !
    !
    !
    !
    • Then add persistent entities that are annotated with 

    grails.persistence.Entity
    18
    compile  "org.grails:gorm-­‐mongodb-­‐spring-­‐
    boot:1.1.0.RELEASE"

    View Slide

  19. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Take GORM to the next level
    Tips & Tricks

    View Slide

  20. GORM Tips & Tricks
    • Understanding where queries
    • Working with DetachedCriteria
    • Using formula and column readers / writers
    • Going asynchronous
    20

    View Slide

  21. Where Queries
    • Type-safe, composable query API
    21
    !
    DetachedCriteria  query  =          
           Person.where  {  
                   lastName  ==  "Simpson"  
           }  
    !
    def  results  =  query.list()

    View Slide

  22. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Demo: Where Queries

    View Slide

  23. Hibernate Subqueries
    • Perform nested “in” or “notIn” sub queries that span domain
    classes using where queries:
    23
    def  employees  =  Employee.where  {  
           region.continent  in  ['APAC',  "EMEA"]  
    }.id()  
    !
    def  results  =  Sale.where  {  
         employee  in  employees  &&  total  >  50000  
    }.employee.list()

    View Slide

  24. Hibernate Correlated Subqueries
    • Declare aliases using “def” for cross query references:
    24
    def  query  =  Employee.where  {  
           def  em1  =  Employee  
           exists  Sale.where  {  
                   def  s1  =  Sale  
                   def  em2  =  employee  
                   return  em2.id  ==  em1.id  
           }.id()  
    }  
    def  results  =  query.list()

    View Slide

  25. Hibernate Column Formula
    • A column can be a read-only formula
    25
    class  Product  {  
           Float  price  
           Float  taxRate  
           Float  tax  
           static  mapping  =  {  
                   tax  formula:  'PRICE  *  TAX_RATE'  
           }  
    }

    View Slide

  26. Hibernate Column Readers/Writers
    • New in 2.4: Implement custom column readers and writers
    to transform data when written or read from the database.
    26
    class  Name  {  
           String  title  
           static  mapping  =  {  
                   title  write:'UPPER(?)',  
                             read:'REPEAT(title,  2)'  
           }  
    }

    View Slide

  27. Asynchronous GORM
    • Database operations are blocking
    • Can be helpful to isolate these blocking operations on a
    separately managed thread
    • Work underway in some NoSQL datastore on fully
    asynchronous drivers (MongoDB, CouchDB etc.)
    • No usable asynchronous SQL/JDBC drivers on the horizon
    (to my knowledge)
    27

    View Slide

  28. Async Namespace
    • Any GORM method can become Async
    28
    import  static  grails.async.Promises.*  
    !
    def  p1  =  Person.async.get(1L)  
    def  p2  =  Person.async.get(2L)  
    def  p3  =  Person.async.get(3L)  
    def  results  =  waitAll(p1,  p2,  p3)

    View Slide

  29. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Demo: Async GORM

    View Slide

  30. Async Tasks
    • Individual async method calls often too fine grained, use
    task method to implement Async GORM tasks
    30
    def  promise  =  Person.async.task  {  
           withTransaction  {  
                 def  person  =  findByFirstName("Homer")  
                 person.firstName  =  "Bart"  
                 person.save(flush:true)          
           }  
    }  
    Person  updatedPerson  =  promise.get()

    View Slide

  31. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Go schemaless!
    Jumping into MongoDB

    View Slide

  32. GORM for MongoDB
    • Geospacial querying
    • GeoJSON models
    • Full text search
    • Schemaless domain models
    • Projections via MongoDB
    aggregation
    • Stateless and Stateful modes
    • Custom user types
    32

    View Slide

  33. GORM for MongoDB Internals
    • MongoEntityPersister implements persistence
    • MongoQuery implements querying aggregation
    • MongoSession implements batch inserts, updates and
    deletes
    • MongoGormStaticApi adds extra GORM methods
    • GeoJSONType and subclasses implement GeoJSON
    custom types
    • https://github.com/grails/grails-data-mapping/tree/master/
    grails-datastore-gorm-mongodb
    33

    View Slide

  34. GORM, MongoDB & GeoJSON
    • Geo Data in MongoDB represented by GeoJSON types
    – http://geojson.org
    • Package grails.mongodb.geo contains GeoJSON
    types
    – Point, Polygon, LineString, MultiPoint,
    MultiLineString, MultiPolygon,
    GeometryCollection
    34

    View Slide

  35. Geospacial Querying
    35
    def  point  =  new  Point(2,  1)  
    def  p  =  new  Place(point:  point)  
    !
    def  poly1  =  Polygon  
         .valueOf([  [0.0,  0.0],  [3.0,  0.0],  
    [3.0,  3.0],  [0.0,  3.0],  [0.0,  0.0]  ])  
    !
    Place.findByPointGeoWithin(poly1)  

    View Slide

  36. MongoDB Text Search
    • Create text indices and use methods
    36
    Product.search('"Coffee  Cake"')  
                                     .size()  ==  1  
    Product.searchTop("cake").size()  ==  4  
    Product.searchTop("cake",3).size()  ==  3  
    Product.countHits('coffee')  ==  5  

    View Slide

  37. Schemaless Dynamic Properties
    • Add dynamic properties with the subscript operator
    37
    def  p  =  new  Plant(name:"Pineapple")  
    p.save()  
    p["color"]  =  "Yellow"  
    p["hasLeaves"]  =  true  

    View Slide

  38. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Demo: GORM for MongoDB

    View Slide

  39. Other Implementations
    • Neo4j
    – http://grails.org/plugin/neo4j
    • Redis GORM
    – http://grails.org/plugin/redis-gorm
    • GORM for REST
    – http://grails.org/plugin/gorm-rest-client
    • Cassandra
    – https://github.com/grails/grails-data-mapping/
    39

    View Slide

  40. © 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
    Spin up GORM inside a unit test
    Unit Testing GORM

    View Slide

  41. Hibernate in Unit Tests
    • Add a dependency on grails-datastore-test-
    support
    !
    !
    !
    • Provides HibernateTestMixin that will load Hibernate
    inside a unit test
    41
    test  "org.grails:grails-­‐datastore-­‐test-­‐
    support:1.0-­‐grails-­‐2.4"

    View Slide

  42. Hibernate in Unit Tests
    42
    import  grails.test.mixin.TestMixin  
    import  grails.test.mixin.gorm.Domain  
    import  grails.test.mixin.hibernate.*  
    import  spock.lang.Specification  
    !
    @Domain(Person)  
    @TestMixin(HibernateTestMixin)  
    class  PersonSpec  extends  Specification  {  
         …  
    }

    View Slide

  43. Summary
    • GORM provides a rich and diverse ecosystem
    • Goes far beyond relational databases
    • Can be used standalone or within Grails
    • Great area to contribute to!
    43

    View Slide

  44. !
    Q & A

    View Slide

  45. Stay Connected.
    !
    !
    !
    !
    Web: grails.org
    StackOverflow: http://stackoverflow.com/tags/grails
    Twitter: http://twitter.com/grailsframework
    LinkedIn: http://linkedin.com/groups/Grails-User-Group-39757
    Google+: https://plus.google.com/communities/
    109558563916416343008

    View Slide