m Gorm
Key Points
- Gorm is an ORM for RDBs ( specifically MySQL,Postgres, MS SQL, sqlite ) with the ability to create dialects to support other databases
- Gorm uses Groovy scripting to define data models and relations
- Gorm models can be used in Grails to scaffold Web applications and REST services
References
Key Concepts
Groovy 3 Key Features
http://groovy-lang.org/releasenotes/groovy-3.0.html
supports JDK 11, JDK 9 and JDK 8 at runtime
onlyJDK 11, JDK 9 supported at build time
Java-style Lambda syntax
The Java syntax for lambda expressions is now supported.
Examples:
(1..10).forEach(e -> { println e })
assert (1..10).stream()
.filter(e -> e % 2 == 0)
.map(e -> e * 2)
.toList() == [4, 8, 12, 16, 20]
The normal variants are supported and Groovy adds additional features such as default parameter values:
// general form
def add = (int x, int y) -> { def z = y; return x + z }
assert add(3, 4) == 7
// curly braces are optional for a single expression
def sub = (int x, int y) -> x - y
assert sub(4, 3) == 1
// parameter types are optional
def mult = (x, y) -> x * y
assert mult(3, 4) == 12
// no parentheses required for a single parameter with no type
def isEven = n -> n % 2 == 0
assert isEven(6)
assert !isEven(7)
// no arguments case
def theAnswer = () -> 42
assert theAnswer() == 42
// any statement requires braces
def checkMath = () -> { assert 1 + 1 == 2 }
checkMath()
// example showing default parameter values (no Java equivalent)
def addWithDefault = (int x, int y = 100) -> x + y
assert addWithDefault(1, 200) == 201
assert addWithDefault(1) == 101
Potential Value Opportunities
Potential Challenges
Bug> Groovyconsole can't open groovy file from menu or cli
bug> can't open a file from groovyconsole using the file menu
workaround> use CTL + O
- open groovyconsole normally
- use CTL + O to open file selector window
- select a groovy file
- press Enter
- << file opens normally in groovy console
Candidate Solutions
Step-by-step guide for Example
GORM Shell Scripting needs transaction context
http://daviddawson.me/blog/2017/09/06/groovy-gorm-shell-script.html
Set a transaction context for a data source in GORM
Gorm has come along well and is pretty isolated from the surrounding Grails infrastructure now. All you need to do is to create a HibernateDatastore
(or other) and pass in a config and your domain classes for initialisation. Then, you can start to use them as you do in Grails.
One rub is that there is no natural place to wrap a transactional Session around. This appears as a hiernate exception related to no session being present. This is something often not noticed in a grails app, as its all created automatically by Grails, and is also created by a full fat standalone Gorm app when you’re using services with any form of transactional annotation. Yet, you need a session to use hibernate, which the RDBMS version of Gorm uses.
The solution is to use the .withTransaction
method added onto all grails domain classes. This creates a session and puts it into the thread context.
I did a light bit of syntax sugaring to hide that stuff and make things more readable, and its good to go!
#!/usr/bin/env groovy @Grapes([ @Grab("org.grails:grails-datastore-gorm-hibernate5:6.1.4.RELEASE"), @Grab("com.h2database:h2:1.4.192"), @Grab("org.apache.tomcat:tomcat-jdbc:8.5.0"), @Grab("org.apache.tomcat.embed:tomcat-embed-logging-log4j:8.5.0"), @Grab("org.slf4j:slf4j-api:1.7.10") ]) import grails.gorm.annotation.Entity import org.grails.datastore.gorm.GormEntity import org.grails.orm.hibernate.HibernateDatastore // Create the domain classes you want @Entity class Person implements GormEntity<Person> { String firstName String lastName static mapping = { firstName blank: false lastName blank: false } } //Guts of the script, do your db stuff here with the power of Gorm gormScript { new Person(firstName: 'Dave', lastName: 'Ronald').save() new Person(firstName: 'Jeff', lastName: 'Happy').save() new Person(firstName: 'Sergio', lastName: 'del Amo').save() new Person(firstName: 'Monica', lastName: 'Crazy').save() println "People = ${Person.count()}" def sergio = Person.findByFirstName("Sergio") println "Got ${sergio.firstName} ${sergio.lastName}" } def gormScript(Closure exec) { Map configuration = [ 'hibernate.hbm2ddl.auto':'create-drop', 'dataSource.url':'jdbc:h2:mem:myDB' ] HibernateDatastore datastore = new HibernateDatastore( configuration, Person) Person.withTransaction { exec() } }
sample code block