8. Datasource environments { development { dataSource { dbCreate = "create-drop" // one of 'create', 'create-drop','update' url = "jdbc:hsqldb:mem:devDB" } } test { dataSource { dbCreate = "update" url = "jdbc:hsqldb:mem:testDb" } } production { dataSource { dbCreate = "update" url = "jdbc:hsqldb:file:prodDb;shutdown=true" } } }
9.
10. Team domain class > grails create-domain-class team class Team { String name String championship String city Long supporters Integer foundationYear static hasMany = [players: Player] static constraints = { name (unique: true, blank: false, size: 2..30) championship (blank: false, inList: ['Serie A', 'Serie B', 'Serie C1', 'Serie C2']) city (blank: true, size: 2..25) supporters (nullable: true) foundationYear (nullable: true) } }
11. Player domain class > grails create-domain-class player class Player { String name String lastName String city Date birth String email static belongsTo = [team: Team] static constraints = { name (blank: false, size: 2..30) lastName (blank: false, size: 2..30) city (blank: true, size: 2..25) birth (nullable:true) email (blank: true, email: true) } }
12. GORM Associations – One to one Unidirectional - class Person { BillingAddress address } class BillingAddress { ... } Bidirectional (no update / delete cascading) - class Person { BillingAddress address } class BillingAddress { Person person }
13. GORM Associations – One to one Bidirectional (update / delete cascading) - class Person { BillingAddress address } class BillingAddress { static belongsTo = [person: Person] }
14. GORM Associations – One to many Update cascading, no delete - class Team { static hasMany = [players: Player] } class Player { ... } Update / delete cascading - class Team { static hasMany = [players: Player] } class Player { static belongsTo = [team: Team] }
15.
16.
17. Team controller > grails generate-controller team Every action is implemented as a closure
18. Team controller - List def list = { if (!params.max) params.max = 10 [ teamList: Team.list( params ) ] } - params is a map containing the request parameters - list is a GORM method, can take parameters: - max, offset, order, sort, ignoreCase, fetch - No explicit return statement - No explicit view
19. Team controller - Show def show = { def team = Team.get( params.id ) if (!team) { flash.message = "Team not found with id ${params.id}" redirect(action: list) } else { return [ team : team ] } } - get is a GORM method - flash is a new scope introduces by Grails - explicit return statement
20. Team controller - Save def save = { def team = new Team(params) if(!team.hasErrors() && team.save()) { flash.message = "Team ${team.id} created" redirect(action: show, id: team.id) } else { render(view: 'create', model: [team: team]) } } - save performs validation and return null if errors are found - explicit view declarations (render)
27. Dynamic finders - findBy and findAllBy - def team = Team.findByName(‘Juventus’) - def teamList = Team.findAllByCity(‘Milano’) - Composition of properties, boolean logic and comparators: - and, or - LessThan, LessThanEquals, GreaterThan, GreaterThanEquals, Like, Ilike, NotEqual, Between, IsNotNull, IsNull es: Team.findAllByCityLikeAndSupportersGreaterThan(‘Milano’, 1000, [max: 3, offset: 2, sort: "name", order: "desc"])
28. Multiaction search form <g:form name="searchForm"> <input type="text" name="searchQuery" /> <g:actionSubmit value="Search by Team" action="teamSearch" /> <g:actionSubmit value="Search by City" action="citySearch" /> </g:form> - Each button sends the form to a different action
29. Hql queries def teamSearch = { def playerList = Player.findAll("from Player as p where p.team.name = ?", ["${params.searchQuery}"]) render(view: 'list', model: [playerList: playerList]) } - You can use HQL queries with named and pagination parameters: es: Player.findAll("from Player as p where p.team.name = :teamName order by p.lastName asc", [teamName: "Juventus"], [max:10, offset:20])
30. Hibernate Criteria def citySearch = { def c = Player.createCriteria() def playerList = c.list { ilike("city", "%${params.searchQuery}%") } render(view: 'list', model: [playerList: playerList]) } - Uses a Groovy builder to hide Hibernate's Criteria API complexity
31. Hibernate Criteria A more complex example: def c = Account.createCriteria() def results = c { like("holderFirstName", "Fred%") and { between("balance", 500, 1000) eq("branch", "London") } maxResults(10) order("holderLastName", "desc") }
32. Pagination problem After the search we see a pagination error: we must modify the generated action and gsp: