Share
Embed
Advanced GORM - Beyond Relational
Talk by Graeme Rocher at SpringOne2GX 2014 on Advanced GORM
graemerocher
September 10, 2014
Transcript
45 slides
-
© 2014 SpringOne 2GX. All rights reserved. Do not distribute
without permission. Advanced GORM - Beyond Relational By 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 -
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=FALS E", '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-mongodb 33 -
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 -
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