Download - Advanced GORM - Beyond Relational

Transcript
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