leftovers...

about grails groovy

Grails-1.0.*からGrails-1.1への〜 Pt.3 まだ最終版じゃないから何とも言えないけど・・・GORM・・・

Grails-1.0.*からGrails-1.1への〜 Pt.2 Grails起動部分をコードリーディングしてみた。 - leftovers...からの続編「GrailsScriptRunner#callPluginOrGrailsScript(String scriptName)」を書こうとおもったのですが・・・
その前のエントリーGrails-1.0.*からGrails-1.1への〜 Pt.1 - leftovers... でザックリと起動するところまではできて、動作検証していくと、なんだかGORM関連におかしな動きが!
というわけで、まとめておきます。

オチから書くと、

Many-to-Manyのジョインテーブルのデフォルト値がかわってる!

検証の流れ

必要な物
grails-1.0.x (検証では、1.0.5-SNAPSHOT revision 8587.)
grails-1.1 (検証では、1.1-SNAPSHOT revision 8612.)

初心者の方はGrailsインストール+簡単な認証付きアプリをサックリ作成して動作確認。 - leftovers...も参考にしてね。

  1. grails-1.0.xで、Grailsアプリケーションを作成、プロジェクトフォルダへ移動
  2. grails install-plugin acegi でacegiプラグインをインストール (acegi-0.5.1)

理由:コマンドで簡単にMany-to-ManyなGrailsアプリケーションが作れるから。

  1. M-to-Mなドメインクラス達を作成 grails create-auth-domains
  2. データセット用にユーザ管理画面を作成 grails generate-manager
  3. データの違いが見たいので、PROJECT_HOME/grails-app/conf/DataSource.groovyの内容を変更してHSQLDBのファイルに保存変更する。
environments {
	development {
		dataSource {
			dbCreate = "update" // one of 'create', 'create-drop','update' //ここを変更
			url = "jdbc:hsqldb:file:devDb;shutdown=true" //ここを変更
		}
	}
  1. grails run-app で起動して、権限とユーザを追加
  2. ログインできるか確認
  3. 動作確認できたら、一応、プロジェクトフォルダを別名で他の所へ保存しておく。(後での確認用)


では、ここから、grails-1.1へアップグレード

  1. 環境等をgrails-1.1に変更して、 grails upgradeでザックリ更新。
  2. プラグインのパスを設定するため BuildConfig.groovyを作成。

内容は、

grails.plugin.location."acegi"="./plugins/acegi-0.5.1"
  1. それでは、起動! grails run-app

ここで、ログイン
ログインできない!
HSQLDBをfileモードで使ってるのでDBの内容は残っているハズですが、ログイン時にユーザに権限の設定が無いと出ます。
そこで、ユーザの内容をユーザ管理から見てみると、何故かRolesが設定されていないので設定して保存、そして、HSQLDBのファイルをdevDb.*を覗いてみると、なんと、Many-to-Manyのジョインテーブルが新しく作られている!
それも、テーブル名がAUTHORITY_PEOPLE!(元は、AUTHORITY_PERSON)、そりゃないよ!

ここで、Grails Tips
GORMでのM-to-Mとかのジョインテーブルは、設定しない場合は、各ドメイン名でのジョインテーブルが作られます。例えば今回の場合は、PersonとAuthorityなので、AUTHORITY_PERSON。この内容Grailsの公式ドキュメント 5.5.2.1 Table and Column Namesにも書いてあります。
#ただ、まぁ、ドキュメントが全て正しいかというと、OSSだし開発途中だし間違いも仕様変更もあるので、動いた形が本物・・・*1
で、AUTHORITY_PEOPLEになっているのは何故???
つまり

static hasMany = [people: Person]

ここの、peopleが設定されたのですね!そかそか:)
納得するまえに、どうにかしなくてはならないので、
そのドキュメントの近くを読むとジョインテーブルの名前設定方法も書いてあります。
今回の例では、grails-app/domains/Person.groovyには、以下のようにmappingを追加。

class Person {
  static transients = ['pass']
  static hasMany = [authorities: Authority]
  static belongsTo = Authority
  static mapping = {
    authorities column:'AUTHORITIES_ID',joinTable:'AUTHORITY_PERSON'
  }
 /** 省略 ***/
}

そして、grails-app/domains/Authority.groovyには、以下のようにmappingを追加

class Authority {
  static hasMany = [people: Person]
  static mapping = {
    people column:'PEOPLE_ID',joinTable:'AUTHORITY_PERSON'
  }
 /** 省略 ***/
}

こうして、mappingの設定で調整することによってどうにかなる物なんです。
但し、他のDBでは試していないのですが、HSQLDBでは、CONSTRAINT FK00000000 FOREIGN KEY(AUTHORITIES_ID)な感じのを作れないよって、エラーが出たので、CONSTRAINT関連は、HSQLDBのファイルを直接操作して・・・・・で回避。

今回のまとめ、

  • ジョインテーブルの名称が変わるから、テーブル名注意
  • ジョインテーブルの名称を設定すると良いよ

*1:基本受け身です