ドメインクラスのDDLを見てみる

テーブル自動生成はHibernateのSchemaExport(hbm2ddl)を使っているので、特にGrailsだからというものではないのですが自動生成されるドメインクラスのテーブルを見てみます。grails-app/conf/Config.groovyでhibernate="off"となっている部分を"on"に変えると、HibernateSQLがログに出力されるようになります。
テスト用のドメインクラスは↓でone-to-manyの関連が設定してあります。DBはHSQLです。

class Author {
    static hasMany = [ books : Book ]
    String name
}

class Book {
    static belongsTo = [author:Author]
    String title
    String description

    Date dateCreated
    Date lastUpdated
}

これだと、

-- Authorテーブル
create table author (
    id bigint generated by default as identity (start with 1), 
    version bigint not null, 
    name varchar(255) not null, 
    primary key (id)
)
-- Bookテーブル
create table book (
    id bigint generated by default as identity (start with 1),
    version bigint not null,
    author_id bigint not null,
    date_created timestamp not null,
    description varchar(255) not null, 
    last_updated timestamp not null, 
    title varchar(255) not null,
    primary key (id)
)
-- 外部キー
alter table book add constraint FK2E3AE9CD85EDFA foreign key (author_id) references author

こうなります。

constraint

基本的には全ての列が"not null"で定義されます。BootStrap.groovyでテストデータを挿入しようとしたときに、nullのプロパティがあるために挿入されず無視されてしまい、ちょっとはまりました。
nullを許可する場合には以下の様にconstraintで設定します。また、Stringのプロパティはvarchar(255)で定義されていますが、サイズを変更する場合にもconstraintで設定できます。

class Book {
   static belongsTo = [author:Author]
   static constraints = {
	   description(nullable:true, maxSize:1000)
   }
   String title
   String description
}

これだと、

create table book (
    〜
    description varchar(1000), 
    〜

こうなります。

mapping

列の型自体を変更する場合にはmappingに設定します。

class Book {
   static belongsTo = [author:Author]
   String title
   String description
   static mapping = {
	   description type:'text'
   }
}

これだと

create table book (
    〜
    description longvarchar not null,
    〜
)

こうなります。
また、自動でバージョン管理用の列"version"が追加されますが、自動バージョン管理をやめる場合は、以下のようにmappingに設定します。

class Book {
   static belongsTo = [author:Author]
   String title
   String description
   static mapping = {
	   version false
   }
}

これで、version列とバージョンの管理はなくなります。

関連

関連について書いたときに、One-to-manyの場合にbelongsToを外すと連鎖削除がされないようなことを書いたのですが、実際のテーブルを見てみました。

class Author {
    static hasMany = [ books : Book ]
    String name
}

class Book {
    // static belongsTo = [author:Author]
    String title
}

単純に外部キーが設定されないだけではなく、author_bookという連関テーブルが作られるようです。

create table author (id bigint generated by default as identity (start with 1), version bigint not null, name varchar(255) not null, primary key (id))
create table author_book (author_books_id bigint, book_id bigint)
create table book (id bigint generated by default as identity (start with 1), version bigint not null, title varchar(255) not null, primary key (id))
alter table author_book add constraint FK2A7A111D3FA913A foreign key (book_id) references book
alter table author_book add constraint FK2A7A111DC46A00AF foreign key (author_books_id) references author

以下の様にmany-to-manyの関連を設定すると、

class Author {
    static hasMany = [ books : Book ]
    String name
}

class Book {
     static belongsTo = Author
     static hasMany = [authors:Author]
     String title
}

以下の様なDDLになります。

create table author (id bigint generated by default as identity (start with 1), version bigint not null, name varchar(255) not null, primary key (id))
create table author_book (authors_id bigint not null, books_id bigint not null, primary key (books_id, authors_id))
create table book (id bigint generated by default as identity (start with 1), version bigint not null, title varchar(255) not null, primary key (id))
alter table author_book add constraint FK2A7A111DA6B0CB7B foreign key (authors_id) references book
alter table author_book add constraint FK2A7A111DED1C647B foreign key (books_id) references author