Advanced GORM - Beyond Relational
description
Transcript of Advanced GORM - Beyond Relational
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Advanced GORM - Beyond RelationalBy Graeme Rocher
Agenda
§ Understanding GORM Internals § GORM Standalone § Tips and Tricks § Jumping into MongoDB § Unit testing with GORM § Summary / Q & A
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
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Understanding what makes GORM tick
GORM Internals
Grails Data Mapping Project
• https://github.com/grails/grails-data-mapping
5
Built by Travis
• https://travis-ci.org/grails/grails-data-mapping
6
Developer Documentation
• http://grails.github.com/grails-data-mapping/
7
Important Subprojects• grails-datastore-core
– Core low level API
• grails-datastore-gorm– GORM API layer
• grails-datastore-gorm-tck– Test Suite
8
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Demo: Code Walkthrough
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
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Use GORM outside of Grails
GORM Standalone
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
Standalone Entities• Annotated with grails.persistence.Entity
13
@Entity class Person { String name static constraints = { name blank:false } }
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)
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()
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Demo: GORM Standalone
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"
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"
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Take GORM to the next level
Tips & Tricks
GORM Tips & Tricks• Understanding where queries • Working with DetachedCriteria • Using formula and column readers / writers • Going asynchronous
20
Where Queries• Type-safe, composable query API
21
DetachedCriteria<Person> query = Person.where { lastName == "Simpson" }
def results = query.list()
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Demo: Where Queries
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()
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()
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' } }
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)' } }
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
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)
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Demo: Async GORM
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()
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Go schemaless!
Jumping into MongoDB
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
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
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
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)
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
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
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Demo: GORM for MongoDB
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
© 2014 SpringOne 2GX. All rights reserved. Do not distribute without permission.
Spin up GORM inside a unit test
Unit Testing GORM
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"
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 { … }
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
Q & A
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