Grails z MySQL

Z Jacek Laskowski - Wiki Projektanta Java EE

Domyślna konfiguracja Grails obejmuje uruchomienie aplikacji z wbudowaną bazą danych HSQL. Takie podejście pozwala na natychmiastowe budowanie aplikacji webowych bez konieczności zestawiania środowiska uruchomieniowego z bazą danych. Po prostu ją mamy. W tym artykule przedstawię, co jest potrzebne do uruchomienia aplikacji grailsowej z MySQL.

Rozpoczynamy od pobrania MySQL z jego strony domowej mysql.org wraz ze sterownikiem JDBC - Connector/J. Instalacja sprowadza się do wykonania serii kroków z pomocą asystenta instalacji (baza danych) bądź rozpakowania do wybranego katalogu (baza danych i sterownik JDBC).

W przypadku systemu MS Windows uruchomienie/zatrzymanie MySQL to uruchomienie/zatrzymanie usługi MySQL poleceniami net stop MySQL oraz net start MySQL.

$ net start MySQL
The MySQL service is starting..
The MySQL service was started successfully.

$ net stop MySQL
The MySQL service is stopping.
The MySQL service was stopped successfully.

Stwórzmy przykładową aplikację, która początkowo korzysta z HSQL, a w kolejnym kroku zdefiniujemy konfigurację uruchomieniową z MySQL.

Zaczynamy od stworzenia struktury katalogowej projektu poleceniem grails create-app grailsmysql.

$ grails create-app grailsmysql
Welcome to Grails 1.1 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: c:/apps/grails

Base Directory: C:\projs\sandbox
Running script c:\apps\grails\scripts\CreateApp_.groovy
Environment set to development
    [mkdir] Created dir: C:\projs\sandbox\grailsmysql\src
...
Executing hibernate-1.1 plugin post-install script ...
Plugin hibernate-1.1 installed
Created Grails Application at C:\projs\sandbox/grailsmysql

W zasadzie uruchomienie grails create-app jest stworzeniem zrębu aplikacji, gdyż już w tym momencie możliwe jest jej uruchomienie (poleceniem grails run-app). Nie miejmy jednak złudzeń, że owa aplikacja sprowadzi się do pojedynczej strony powitalnej, która wyświetla listę dostępnych kontrolerów, a skoro nie mamy jeszcze żadnego, pojawi się jedynie statyczny tekst.

Przechodzimy do katalogu projektu grailsmysql.

$ cd grailsmysql/

Kolejnym krokiem jest utworzenie klasy dziedzinowej pl.jaceklaskowski.grails.Ksiazka poleceniem grails create-domain-class pl.jaceklaskowski.grails.Ksiazka.

$ grails create-domain-class pl.jaceklaskowski.grails.Ksiazka
Welcome to Grails 1.1 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: c:/apps/grails

Base Directory: C:\projs\sandbox\grailsmysql
Running script c:\apps\grails\scripts\CreateDomainClass.groovy
Environment set to development
    [mkdir] Created dir: C:\projs\sandbox\grailsmysql\grails-app\domain\pl\jaceklaskowski\grails
Created DomainClass for Ksiazka
    [mkdir] Created dir: C:\projs\sandbox\grailsmysql\test\unit\pl\jaceklaskowski\grails
Created Tests for Ksiazka

Dla stworzonej klasy dziedzinowej Ksiazka tworzymy odpowiedni kontroler poleceniem grails create-controller pl.jaceklaskowski.grails.Ksiazka.

$ grails create-controller pl.jaceklaskowski.grails.Ksiazka
Welcome to Grails 1.1 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: c:/apps/grails

Base Directory: C:\projs\sandbox\grailsmysql
Running script c:\apps\grails\scripts\CreateController.groovy
Environment set to development
    [mkdir] Created dir: C:\projs\sandbox\grailsmysql\grails-app\controllers\pl\jaceklaskowski\grails
Created Controller for Ksiazka
    [mkdir] Created dir: C:\projs\sandbox\grailsmysql\grails-app\views\ksiazka
Created Tests for Ksiazka

Modyfikujemy klasę kontrolera KsiazkaController (plik grails-app/controllers/pl/jaceklaskowski/grails/KsiazkaController.groovy) tak, aby zawierała poniższą treść:

package pl.jaceklaskowski.grails

class KsiazkaController {

    def scaffold = Ksiazka
}

Istotnym elementem kontrolera jest wykorzystanie dynamicznego rusztowania (ang. dynamic scaffolding), gdzie widoki odpowiadające akcjom CRUD (ang. Create-Read-Update-Delete) są tworzone w pamięci, dynamicznie. Wystarczy zdefiniować statyczną zmienną scaffold z wartością, która wskazuje na obsługiwaną klasę dziedzinową (wartość to nazwa klasy, jednakże w Groovy Ksiazka == Ksiazka.class i dodawanie .class nie jest konieczne).

Zmieniamy treść klasy dziedzinowej Ksiazka (plik grails-app/domain/pl/jaceklaskowski/grails/Ksiazka.groovy) na następującą:

package pl.jaceklaskowski.grails

class Ksiazka {

    String tytul
    String autor
}

W tym momencie możemy już uruchomić aplikację poleceniem grails run-app.

$ grails run-app
Welcome to Grails 1.1 - http://grails.org/
Licensed under Apache Standard License 2.0
Grails home is set to: c:/apps/grails

Base Directory: C:\projs\sandbox\grailsmysql
Running script c:\apps\grails\scripts\RunApp.groovy
Environment set to development
...
Running Grails application..
Server running. Browse to http://localhost:8080/grailsmysql

Po jej uruchomieniu, wystarczy skierować przeglądarkę na adres http://localhost:8080/grailsmysql i cieszyć się "pięknem" naszej aplikacji grailsowej.

Grafika:grails-welcome.gif

Wykonanie kilku czynności w aplikacji powinno upewnić nas, że domyślna konfiguracja bazodanowa z HSQL działa poprawnie. Pora włączyć konfigurację MySQL.

Jak mogliśmy zauważyć podczas uruchamiania poleceń grails, jednym z komunikatów była informacja z jakiego środowiska uruchomieniowego korzystamy, np.:

Environment set to development

W tym przykładzie, konfiguracja środowiska to środowisko rozwojowe development. W Grails istnieją 3 predefiniowane konfiguracje środowiska - development, test oraz production. Wskazanie, które powinno być bieżące to uruchomienie polecenia grails z parametrem JVM grails.env lub po prostu z podaniem nazwy skróconej konfiguracji jako drugi parametr grails, np.

$ grails test run-app
...
Environment set to test

Wykorzystajmy tę wiedzę do zdefiniowania własnej konfiguracji mysql z bazą MySQL w pliku grails-app/conf/DataSource.groovy. Plik DataSource.groovy jest skryptem Groovy, który odpowiada za konfigurację bazodanową i tam właśnie znajdziemy konfigurację domyślną z HSQL.

Plik grails-app/conf/DataSource.groovy powinien zawierać następującą treść:

dataSource {
 pooled = true
 driverClassName = "org.hsqldb.jdbcDriver"
 username = "sa"
 password = ""
}
hibernate {
 cache.use_second_level_cache=true
 cache.use_query_cache=true
 cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
}
// environment specific settings
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"
  }
 }
 mysql {
  dataSource {
   dbCreate = "create-drop"
   url = "jdbc:mysql://localhost/grailsmysqldb"
   driverClassName = "com.mysql.jdbc.Driver"
   dialect ="org.hibernate.dialect.MySQLDialect"
   username = "root"
   password = "passw0rd"
  }
 }
}

Na uwagę zasługuje ostatnia "sekcja" mysql, gdzie definiujemy źródło danych wskazujące na MySQL (w zasadzie to mysql oraz dataSource to wywołania metod akceptujących pojedynczy parametr, który jest de facto domknięciem).

Dostęp do bazy danych w Javie wymaga właściwego sterownika JDBC. W przypadku MySQL będzie to Connector/J jako plik mysql-connector-java-5.1.7-bin.jar, który umieszczamy w katalogu lib projektu. Konieczne jest ponowne uruchomienie aplikacji.

Ostatnim krokiem jest stworzenie bazy danych w MySQL. W naszej konfiguracji mysql w DataSource.groovy założyliśmy nazwę bazy grailsmysqldb. Stworzenie bazy to wykonanie polecenia create database grailsmysqldb.

mysql> create database grailsmysqldb;

Po tych zmianach uruchamiamy aplikację ponownie poleceniem grails -Dgrails.env=mysql run-app.

$ grails -Dgrails.env=mysql run-app
Welcome to Grails 1.1 - http://grails.org/
...
Environment set to mysql
...
Server running. Browse to http://localhost:8080/grailsmysql

Uruchomienie aplikacji http://localhost:8080/grailsmysql i stworzenie książki

Grafika:grails-ksiazka1created.gif

to gwarancja, że aplikacja korzysta z bazy MySQL poprawnie.

Na zakończenie sprawdźmy struktury bazodanowe w MySQL.

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.1.32-community MySQL Community Server (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use grailsmysqldb
Database changed

mysql> show tables;
+-------------------------+
| Tables_in_grailsmysqldb |
+-------------------------+
| ksiazka                 |
+-------------------------+
1 row in set (0.00 sec)

mysql> describe ksiazka;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| version | bigint(20)   | NO   |     | NULL    |                |
| autor   | varchar(255) | NO   |     | NULL    |                |
| tytul   | varchar(255) | NO   |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> select * from ksiazka;
+----+---------+-----------------+----------------+
| id | version | autor           | tytul          |
+----+---------+-----------------+----------------+
|  1 |       0 | Jacek Laskowski | Grails z MySQL |
+----+---------+-----------------+----------------+
1 row in set (0.00 sec)

mysql> quit

Zatem działa jak należy. Gratulacje!

Osobiste