Upload
spring-io
View
688
Download
0
Embed Size (px)
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.
Citation preview
© 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