GORM is one of the keys for the success of Grails, but for a Grails beginner some concepts may be a bit confusing. Even for a long time developer there can be some missconceptions due to the abstractions layers of the framework.
In this talk I’ll try to cover some of the basics of GORM, Hibernate and how to interact with transactions and sessions. I’ll show some of the problems that I had starting with the Grails framework and how I think they are best solved.
Some other topics that I’ll go over are the interaction with GPars, and the differences between “session” and “transaction”.
3. GORM? Really?
Is so easy, the easiestpartof Grails!
Onlyafew POGO's to access the database
Peachy!
4.
5. Some pitfalls
The 'When did I modified thatobject?'
defrenderBook(Stringisbn){
defbook=Book.findByIsbn(isbn)
//Renderasuppercase
book.title=book.title.toUpperCase()
[book:book]
}
6. Some pitfalls
The 'Rollback where are you?'
defbuyBook(Stringuser,StringbookTitle,Longqty){
deffound=Book.findByTitle(bookTitle)
//Saveaneworderfortheuser
deforder=newBookOrder(user:user,book:found,quantity:qty)
order.save()
found.stock=found.stock-1
//Whennotfoundthrowexceptiontorollback
if(found.stock<0){
thrownewException("Thisshouldrollback!")
}
returnfound
}
7. Some pitfalls
The 'Parallelprocessing, It's easy!!'
defprocessOrders(){
deforders=BookOrder.list()
//Parallelupdateorders
GParsPool.withPool(10){
orders.eachParallel{order->
dispatchingService.dispatch(order)
order.sent=true
order.save()
}
}
}
17. Grails initializes the Domain Class
Prepares the relationship properties
Resolves class hierarchy
Add validation capabilities
Integrates domain classes with Spring
34. GORM > Hibernate
GORM provides abeautifulabstraction over hibernate
Convention over configuration
No more complicated XML or annotations
Better collections
42. GORM Entities
Entities have arelationship with the session
This defines a"life-cycle"
Transient -notyetpersisted
Persistent -has asession
Detached -persisted butwithoutsession
50. Some pitfalls
The 'When did I modified thatobject?'
defrenderBook(Stringisbn){
defbook=Book.findByIsbn(isbn)
//Renderasuppercase
book.title=book.title.toUpperCase()
[book:book]
}
51. Some pitfalls
The 'When did I modified thatobject?'
defrenderBook(Stringisbn){
defbook=Book.findByIsbn(isbn)
//Deattachtheobjectfromthesession
book.discard()
//Renderasuppercase
book.title=book.title.toUpperCase()
[book:book]
}
58. Some pitfalls
The 'Rollback where are you?'
defbuyBook(Stringuser,StringbookTitle,Longqty){
deffound=Book.findByTitle(bookTitle)
//Saveaneworderfortheuser
deforder=newBookOrder(user:user,book:found,quantity:qty)
order.save()
found.stock=found.stock-1
//Whennotfoundthrowexceptiontorollback
if(found.stock<0){
thrownewException("Thisshouldrollback!")
}
returnfound
}
59. Some pitfalls
The 'Rollback where are you?'
defbuyBook(Stringuser,StringbookTitle,Longqty){
deffound=Book.findByTitle(bookTitle)
//Saveaneworderfortheuser
deforder=newBookOrder(user:user,book:found,quantity:qty)
order.save()
found.stock=found.stock-1
//Whennotfoundthrowexceptiontorollback
if(found.stock<0){
thrownewRuntimeException("Thisshouldrollback!")
}
returnfound
}
63. Some pitfalls
The 'Concurrency, It's easy!!'
defprocessOrders(){
deforders=BookOrder.list()
//Parallelupdateorders
GParsPool.withPool(10){
orders.eachParallel{order->
dispatchingService.dispatch(order)
order.sent=true
order.save()
}
}
}
64. Thread-local session
Recovers alistof orders
Each item is bound to the requestsession
When we spawn the concurrentthreads the objects don't
know where is their session
deforders=Orders.findTodayOrders()
66. Rule of thumb
Session = Thread
If entityhas recovered byanother thread
Putitin the currentthread session
67. Grails 2.3 Async GORM
The new async GORM solves some problems
Manages the session for the promise
defpromise=Person.async.findByFirstName("Homer")
defperson=promise.get()
68. Grails 2.3 Async GORM
Problem: Objecthas been retrieved byanother thread
After the promise is resolved we have to attach the object
defpromise=Person.async.findByFirstName("Homer")
defperson=promise.get()
person.merge()//Reboundtheobjecttothesession
person.firstName="Bart"
69.
70. Closing thoughts
GORM is averycoolabstraction
You have to be aware of some of how things work
With greatpower, comes greatresponsibility