grailsも結構いいものですよ〜
そろそろSaStrutsを使うのは時代遅れなので、Play FrameworkかGrailsを候補に検討中です。
Playは会社で使いそうなので、自宅ではGrailsを学ぶ事にしました。
ざっくり触っただけですが、PlayはJava JavaしてるFWで、Grailsはjsやrubyのような感じ、という印象です。Playはror風と言ってますが、全然javaの域を超えていないので、SaStrutsやSpringの上位版FWみたいな感じがしました。それと比較してGrailsはgroovyでコーディングするので、javaのような静的言語と全然違う感じです。今までと大分コーディングの仕方が変わります。
習得の容易さやいざという時に馴染んだjavaで何とかできる事を考慮するとPlay。生産性や動的言語への移行をしたいならGrails。個人的には機能的には圧倒的にGrailsの方が多機能なので、Grailsを推します。
話が逸れてしまいましたが、今回の本題はGORM(Grails ORM)です。Grails起動時にGORMがドメインを元にテーブルを自動生成するのですが、中々思うように型はフィールド長やPrimary keyが設定できなかったので、解った範囲でまとめておきたいと思います。
なお、Grailsのバージョンは2.3.4です。
生成したいDDL
以下のDDLをGORMで作成する事を目指します。
mysql> desc address; +--------------------------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------------------+----------+------+-----+---------+-------+ | pref_cd | char(2) | NO | PRI | | | | pref_name | text | YES | | NULL | | | city_cd | char(5) | NO | PRI | | | | city_name | text | YES | | NULL | | | town_street_cd | char(12) | NO | PRI | | | | town_street_name | text | YES | MUL | NULL | | | town_street_name_reverse | text | YES | MUL | NULL | | | latitude | double | YES | | NULL | | | longitude | double | YES | | NULL | | +--------------------------+----------+------+-----+---------+-------+
思うようにいかなかった部分
- versionカラムが勝手に生成されてしまう。
- 型の指定方法。
- 複合キー(複数のPrimary Key)を指定する方法。
- bigint auto_incrementでないカラムをidに指定する方法。
- GORMで生成されるカラムの順番を指定する方法。
では順番に見ていきます。
versionカラムが勝手に生成されてしまう
これは簡単です。
class Address { ・・・略・・・ static constraints = { ・・・略・・・ } static mapping = { version false } }
version flaseを指定するだけです。
型の指定方法
class Address { String prefCd String prefName String cityCd String cityName String townStreetCd String townStreetName String townStreetNameReverse Double latitude Double longitude static constraints = { prefCd maxSize: 2, blank: false, nullable: false prefName maxSize: 191, blank: true, nullable: true cityCd maxSize: 5, blank: false, nullable: false cityName maxSize: 191, blank: true, nullable: true townStreetCd maxSize: 12, blank: false, nullable: false townStreetName blank: true, nullable: true townStreetNameReverse blank: true, nullable: true latitude nullable: true longitude nullable: true } static mapping = { townStreetName sqlType: 'text' townStreetNameReverse sqlType: 'text' } }
こんな感じでmappingの方にsqlTypeで定義できます。
sqlTypeを指定しないとbigintやvarcharになってしまいます。
型+フィールド長を指定する場合、例えば char(2) を定義する場合は以下のようにします。
static constraints = { prefCd blank: false, nullable: false } static mapping = { prefCd sqlType: 'char(2)' }
mappingで型を定義する場合はconstraints側にmaxSizeを設定しても効かないので注意です。
例えば、
static constraints = { prefCd maxSize: 1, blank: false, nullable: false } static mapping = { prefCd sqlType: 'char(2)' }
とした場合、生成されるのはchar(1)ではなくchar(2) になります。
複合キー(複数のPrimary Key)を指定する方法。
GORMは何も指定しないと自動的に id bigint auto_increment primary key を生成してしまいます。
マスター等の場合は自動採番カラムがあると困るので、複合キーを指定したい場合があります。
その場合、以下のように指定します。
class Address implements Serializable { String prefCd String prefName String cityCd String cityName String townStreetCd String townStreetName String townStreetNameReverse Double latitude Double longitude static constraints = { prefCd maxSize: 1, blank: false, nullable: false prefName maxSize: 191, blank: true, nullable: true cityCd blank: false, nullable: false cityName maxSize: 191, blank: true, nullable: true townStreetCd blank: false, nullable: false townStreetName blank: true, nullable: true townStreetNameReverse blank: true, nullable: true latitude nullable: true longitude nullable: true } static mapping = { id composite: ['prefCd', 'cityCd', 'townStreetCd'] prefCd sqlType: 'char(2)' cityCd sqlType: 'char(5)' townStreetCd sqlType: 'char(12)' townStreetName sqlType: 'text' townStreetNameReverse sqlType: 'text' } }
id compositeの部分とimplements Serializableの部分がキモです。リファレンスには書いてありますが、見ないと絶対解らないので注意ですね。
複合主キーを用いるドメインクラスでは、Serializableインターフェイスの実装とequalsとhashCodeメソッドのオーバライドが必要です。 これによって複合キーのプロパティを同一性の算定に利用できるようになります。
http://grails.jp/doc/latest/guide/GORM.html#compositePrimaryKeys
ちなみに複合キーを指定した場合、idカラムは生成されませんでした。
bigint auto_incrementでないカラムをidに指定する方法
これは非常に解りにくく、調べるのに苦戦しました。
複合キーだとjoinの手間がかかったりするので、小規模なマスターの場合、PKのカラムを全て結合したカラムを用意する事があります。
今回は、address_cdをid(Primary Key)として使用します。
address_cdの内訳は、 pref_cd + city_cd + town_street_cd です。
勿論bigintではないですし、auto_incrementではありません。
これを実現するために、最終的に以下のように指定する事で定義できました。
class Address implements Serializable { String prefCd String prefName String cityCd String cityName String townStreetCd String townStreetName String townStreetNameReverse Double latitude Double longitude static constraints = { addressCd blank: false, nullable: false prefCd maxSize: 1, blank: false, nullable: false prefName maxSize: 191, blank: true, nullable: true cityCd blank: false, nullable: false cityName maxSize: 191, blank: true, nullable: true townStreetCd blank: false, nullable: false townStreetName blank: true, nullable: true townStreetNameReverse blank: true, nullable: true latitude nullable: true longitude nullable: true } static mapping = { version false id generator: 'assigned', column: 'address_cd', sqlType: 'char(19)' addressCd insertable: false, updateable: false prefCd sqlType: 'char(2)' cityCd sqlType: 'char(5)' townStreetCd sqlType: 'char(12)' townStreetName sqlType: 'text' townStreetNameReverse sqlType: 'text' } }
重要なのは以下の部分です。
id generator: 'assigned', column: 'address_cd', sqlType: 'char(19)' addressCd insertable: false, updateable: false
generator: 'assigned'は日本語リファレンスには書いてませんが、自動採番でない、自分で設定した値を使う(auto_incrementにしない)という意味になります。
column: 'address_cd'はidはどのカラムなのかを指定します。キャメルケースで書けないのが残念・・
sqlType: 'char(19)'ですが、一見するとaddressCdの方に書きたくなりますが、idの方に記述する必要があります。
insertable: false, updateable: falseですが、すみませんよく解ってません。。こう書かないとエラーになります。
GORMで生成されるカラムの順番を指定する方法
随分調べたのですが、GORMではできないっぽいです。
GORMは前述のドメインクラスを以下のように生成してしまいます。
mysql> desc address; +--------------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------------------+--------------+------+-----+---------+-------+ | address_cd | char(19) | NO | PRI | NULL | | | city_cd | char(5) | NO | | NULL | | | city_name | varchar(191) | YES | | NULL | | | latitude | double | YES | | NULL | | | longitude | double | YES | | NULL | | | pref_cd | char(2) | NO | | NULL | | | pref_name | varchar(191) | YES | | NULL | | | town_street_cd | char(12) | NO | | NULL | | | town_street_name | text | YES | | NULL | | | town_street_name_reverse | text | YES | | NULL | | +--------------------------+--------------+------+-----+---------+-------+
アルファベット順にカラムが並んでしまうのです。
海外のサイトに書いてあったのですが、どうもmigration機能で手動で制御するしかないっぽい???
どなたか知っていたら是非教えて下さい。
【java】Grailsを学ぶ:Vol.01:GORMのDB定義【framework】 - 文系プログラマによるTIPSブログ
【java】Grailsを学ぶ:Vol.02:resource pluginでcss・jsをinclude!【framework】 - 文系プログラマによるTIPSブログ

- 作者: 山田正樹,山本剛,上原潤二,永井昌子,杉山清美,杉浦孝博,笠原史郎,香月孝太,福岡竜一,伊堂寺北斗
- 出版社/メーカー: 翔泳社
- 発売日: 2008/08/26
- メディア: 大型本
- 購入: 3人 クリック: 42回
- この商品を含むブログ (28件) を見る

Play Framework 2徹底入門 JavaではじめるアジャイルWeb開発
- 作者: 掌田津耶乃,原一浩
- 出版社/メーカー: 翔泳社
- 発売日: 2013/12/17
- メディア: 大型本
- この商品を含むブログ (7件) を見る