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 : ドメインクラスが変更されていた場合、テーブル定義を更新する。既存のテーブルは削除しない。
それでは、データベースに格納したいドメインクラス myappRecord を、create-domain-classコマンドにより作成します。ドメインクラスは、MVCにおける'M'に相当します。
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 まで。
inserted by FC2 system