Advanced GORM - Beyond Relational

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

description

In this talk, Grails project lead Graeme Rocher will demonstrate some less known, advanced features of GORM and explore the possibilities offered going beyond the relational database.

Transcript of Advanced GORM - Beyond Relational

Page 1: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Advanced GORM - Beyond RelationalBy Graeme Rocher

Page 2: Advanced GORM - Beyond Relational

Agenda

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

Page 3: Advanced GORM - Beyond Relational

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

Page 4: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Understanding what makes GORM tick

GORM Internals

Page 5: Advanced GORM - Beyond Relational

Grails Data Mapping Project

• https://github.com/grails/grails-data-mapping

5

Page 6: Advanced GORM - Beyond Relational

Built by Travis

• https://travis-ci.org/grails/grails-data-mapping

6

Page 7: Advanced GORM - Beyond Relational

Developer Documentation

• http://grails.github.com/grails-data-mapping/

7

Page 8: Advanced GORM - Beyond Relational

Important Subprojects• grails-datastore-core

– Core low level API

• grails-datastore-gorm– GORM API layer

• grails-datastore-gorm-tck– Test Suite

8

Page 9: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Demo: Code Walkthrough

Page 10: Advanced GORM - Beyond Relational

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

Page 11: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Use GORM outside of Grails

GORM Standalone

Page 12: Advanced GORM - Beyond Relational

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

Page 13: Advanced GORM - Beyond Relational

Standalone Entities• Annotated with grails.persistence.Entity

13

@Entity  class  Person  {          String  name          static  constraints  =  {                  name  blank:false          }  }

Page 14: Advanced GORM - Beyond Relational

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=FALSE",  'sa',  '')  init.configureForDataSource(dataSource)  

Page 15: Advanced GORM - Beyond Relational

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()

Page 16: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Demo: GORM Standalone

Page 17: Advanced GORM - Beyond Relational

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"

Page 18: Advanced GORM - Beyond Relational

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"

Page 19: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Take GORM to the next level

Tips & Tricks

Page 20: Advanced GORM - Beyond Relational

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

20

Page 21: Advanced GORM - Beyond Relational

Where Queries• Type-safe, composable query API

21

DetachedCriteria<Person>  query  =                  Person.where  {                  lastName  ==  "Simpson"          }  

def  results  =  query.list()

Page 22: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Demo: Where Queries

Page 23: Advanced GORM - Beyond Relational

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()

Page 24: Advanced GORM - Beyond Relational

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()

Page 25: Advanced GORM - Beyond Relational

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'          }  }

Page 26: Advanced GORM - Beyond Relational

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)'          }  }

Page 27: Advanced GORM - Beyond Relational

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

Page 28: Advanced GORM - Beyond Relational

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)

Page 29: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Demo: Async GORM

Page 30: Advanced GORM - Beyond Relational

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()

Page 31: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Go schemaless!

Jumping into MongoDB

Page 32: Advanced GORM - Beyond Relational

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

Page 33: Advanced GORM - Beyond Relational

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-mongodb33

Page 34: Advanced GORM - Beyond Relational

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

Page 35: Advanced GORM - Beyond Relational

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)  

Page 36: Advanced GORM - Beyond Relational

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  

Page 37: Advanced GORM - Beyond Relational

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  

Page 38: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Demo: GORM for MongoDB

Page 39: Advanced GORM - Beyond Relational

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

Page 40: Advanced GORM - Beyond Relational

© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.

Spin up GORM inside a unit test

Unit Testing GORM

Page 41: Advanced GORM - Beyond Relational

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"

Page 42: Advanced GORM - Beyond Relational

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  {        …  }

Page 43: Advanced GORM - Beyond Relational

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

Page 44: Advanced GORM - Beyond Relational

Q & A

Page 45: Advanced GORM - Beyond Relational

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