Grails > Grails ORM (GORM) : テーブル作成編
更新日
2014-12-06
広告
GrailsはHibernateを内包しているため、簡単な設定でデータベース(RDBMS)処理を行うことができます。この機能のことを、GORM (Grails Object Relational Mapping)と呼びます。以下、'myapp'というウェブアプリを作成したものとして説明します (Grails 2.x)。
準備
まず、Grailsが使うRDBMS (MySQLとかPostgreSQLとか)を決めます。MySQL以外を使う場合は、BuildConfig.groovyに設定を追加する必要があります。例えば、PostgreSQLを利用する場合は、以下の設定を追加します。dependencies { runtime "postgresql:postgresql:9.1-901.jdbc4" }
これで、GrailsはPostgreSQLのライブラリをレポジトリからダウンロードします。
以降、以下の仮定で説明します。
- RDBMSとしてMySQLを使用
- MySQLのrootユーザのパスワードは'pass'
- 'grails_test'というデータベースが作成されている
テーブルの自動作成
Hibernateの設定は、myapp/grails-app/conf/DataSource.groovy に書きます。このファイルでは、「グローバルな設定」や「テスト時の設定」を書き分けられるようになっています。これにより、実運用時とテスト時で、使用するデータベースを使い分けるといったことが可能になります。// グローバルな設定 dataSource { //url = "jdbc:mysql:///myapp_db" driverClassName = "com.mysql.jdbc.Driver" username = "root" password = "pass" dialect = org.hibernate.dialect.MySQLDialect pooled = true // connection pooling } hibernate { cache.use_second_level_cache = true cache.use_query_cache = false cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' } // 個別の設定 environments { development { // 開発時の設定 dataSource { dbCreate = "create-drop" // one of 'create', 'create-drop', 'update', 'validate', '' url = "jdbc:mysql:///grails_dev" } } test { // テスト時の設定 dataSource { dbCreate = "update" url = "jdbc:mysql:///grails_test" } } : :この場合、テスト用のデータベースとして grails_test を使用します。本番用のデータベースとして myapp_db を使用するつもりですが、まだ何もテストしていないので、コメントアウトしています。また、dbCreateパラメータを指定すると、後述するドメインクラスに対応したテーブルを、Grailsが自動的に作成します。
- create : Grails起動時に、ドメインクラスに対応した既存のテーブルを削除し、新たにテーブルを作成する。
- create-drop : Grails起動時に、ドメインクラスに対応した既存のテーブルを削除し、新たにテーブルを作成する。またGrails終了時に、テーブルを削除する。
- update : ドメインクラスが変更されていた場合、テーブル定義を更新する。既存のテーブルは削除しない。
grails> create-domain-class myapp.myappRecord | Created file grails-app/domain/myapp/MyappRecord.groovy | Created file test/unit/myapp/MyappRecordTests.groovyドメインクラスは、myapp/grails-app/domain以下に配置されます。MyappRecordの初期状態は以下のとおりです。
package myapp class MyappRecord { static constraints = { } }これに、プロパティを追加します。
class MyappRecord { static constraints = { } Integer id Date date Integer money }この状態で、テストの実行(grails test-app)や、コンソールの起動(grails console)を実行すると、DataSource.propertiesのdbCreateパラメータの値に応じて、データベース(grails_test)が更新されます。上記のMyappRecordの場合、以下のようなテーブル myapp_record が作成されます。
mysql> use grails_test; mysql> describe myapp_record; +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | version | bigint(20) | NO | | NULL | | | date | datetime | NO | | NULL | | | money | int(11) | NO | | NULL | | +-------------+--------------+------+-----+---------+----------------+デフォルトで、'id'というプロパティが、テーブルにおけるプライマリーキーとなります。また、その値は auto increment されるようにテーブルが作られます。 versionカラムは、Grailsがテーブルのバージョンを管理するために追加するカラムです。不要であれば、以下のようにします。
class MyappRecord { static mapping = { version false } Integer id Date date Integer money }すると、versionカラムは作られません。ちなみに、以下のように、idプロパティを用意しなくても、idカラムは作成されます。
class MyappRecord { static mapping = { version false } Date date Integer money }インデックスの作成を明示的に指定したい場合は、以下のようにします。
package myapp class MyappRecord { static constraints = { } static mapping = { version false id column: 'id' // プライマリキーのカラムを指定 date index: 'date_idx' // dateプロパティにインデックスを作成することを指定 } Integer id Date date Integer money }dateカラムにインデックスが作成されます。
mysql> describe myapp_record; +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | date | datetime | NO | MUL | NULL | | | money | int(11) | NO | | NULL | | +-------------+--------------+------+-----+---------+----------------+ドメインクラスに対応するテーブル名やカラム名を変更することも可能です。詳細は公式サイトのドキュメントをご覧ください。
既存のテーブルとドメインクラスの対応付け
すでにテーブルが存在していて、それをGrailsから使う場合もあると思います。この場合も、テーブルに対応するドメインクラスを作成すれば、後述するように、簡単にデータベース処理を実装できます。
以下のテーブルを想定します。
- テーブル名: product
- プライマリーキーのカラム名: number
- number カラムは auto increment されない
この場合、以下のようなドメインクラスを用意すればよいです。
class Product { static mapping = { version false id generator: 'assigned' id name: 'number' } Integer number }
既存のテーブルがプライマリキーを auto increment する状態になっていると、RDBMSによっては、ドメインクラスに少し設定が必要になります。例えば、PostgreSQLでserial型を使用すると、auto increment を実現するためにシーケンステーブルが作成されますが、ドメインクラスからシーケンステーブルを指定しなくてはなりません。
例えば、productテーブルにおいて、number カラムが serial 型の場合、デフォルトでは system_number_seq というシーケンステーブルが作成されているはずです。この場合、Productクラスは以下のようにします。
class Product { static mapping = { version false id generator: 'sequence', params: [sequence:'system_number_seq'] id name: 'number' } Integer number = -1 }
numberプロパティに-1を設定していますが、データベース側で自動的に設定されるので問題ありません。
join用のテーブルへの対応
N対Mの関係を表すjoin用のテーブルの、名前やカラム名が既に決まっている場合も、対応可能です。 static mappingの'joinTable'を指定することで、テーブル名やカラム名を指定できます。 詳細はGrailsのドキュメントを参照してください。広告
お問い合わせは sweng.tips@gmail.com まで。