GORM is the data access technology offered by Grails, and one of its spin-offs. This talk covers the 6 most important new features of GORM 6:
GORM without Grails and without Spring.
Multi-tenancy.
RxGORM.
Multiple datasource support.
Unit testing.
Data Services.
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
6 things you need to know about GORM 6
1. 6 things you need to
know about GORM 6
Álvaro Sánchez-Mariscal
@alvaro_sanchez
2. About me
— Coming from Madrid
!
— Developer since 2001 (Java / Spring stack).
— Grails fanboy since v0.4.
— Working @ OCI since 2015: Groovy, Grails & Micronaut!
— Father since 2017!
"
@alvaro_sanchez
3. 1. GORM without Grails /
Spring Boot / Micronaut
@alvaro_sanchez
6. Data Services
Auto-generated persistence logic from interfaces and
abstract classes
@Service(Book)
interface BookService {
Book getBook(Serializable id)
}
@alvaro_sanchez
7. Advantages
— Type safety.
— Signatures statically compiled.
— Testing
— Since they are interfaces, can be easily tested with
Spock mocks.
@alvaro_sanchez
8. Advantages
— Performance.
— No runtime proxies, eveything is compile-time.
— Transaction management.
— Methods are wrapped in a transaction (read-only
for read operations).
@alvaro_sanchez
9. Abstract classes support
@Service(Book)
abstract class BookService {
abstract Book getBook(Serializable id)
abstract Author getAuthor(Serializable id)
Book updateBook(Serializable id, Serializable authorId) {
Book book = getBook(id)
if(book != null) {
Author author = getAuthor(authorId)
if(author == null) throw new IllegalArgumentException("Author does not exist")
book.author = author
book.save()
}
return book
}
}
@alvaro_sanchez
10. Pagination support
Data service:
@Service(Book)
interface BookService {
List<Book> findBooks(String title, Map args)
}
Usage:
List<Book> books = bookService.findBooks(
"The Stand",
[offset:10, max:10, sort:'title', order:'desc']
)
@alvaro_sanchez
11. "Dynamic finder"-like queries
Just that they are statically compiled!
@Service(Book)
interface BookService {
List<Book> findByTitleAndPublishDateGreaterThan(String title, Date publishDate)
}
@alvaro_sanchez
23. Modes
— DATABASE: a separate database with a separate
connection pool is used to store each tenants data.
— SCHEMA: the same database, but different schemas are
used to store each tenants data.
— DISCRIMINATOR - The same database is used with a
discriminator used to partition and isolate data.
@alvaro_sanchez
24. AST Transformations
— @CurrentTenant: resolve the current tenant for the
context of a class or method.
— @Tenant: use a specific tenant for the context of a
class or method
— @WithoutTenant: execute logic without a specific
tenant (using the default connection)
@alvaro_sanchez
25. AST Transformations
@CurrentTenant // resolve the current tenant for every method
class TeamService {
@WithoutTenant // execute the countPlayers method without a tenant id
int countPlayers() {
Player.count()
}
@Tenant({"another"}) // use the tenant id "another" for all GORM logic within the method
List<Team> allTwoTeams() {
Team.list()
}
List<Team> listTeams() {
Team.list(max:10)
}
@Transactional
void addTeam(String name) {
new Team(name:name).save(flush:true)
}
}
@alvaro_sanchez
30. Domain class
class Club implements RxMongoEntity<Club> {
ObjectId id
String name
String stadium
}
@alvaro_sanchez
31. GORM operations
new Book(title:"The Stand")
.save() // Returns an rx.Observable<Book>
.subscribe { Book it ->
// If you don't subscribe, it won't be executed
println "ID = ${book.id}"
}
@alvaro_sanchez