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...も参考にしてね。
- grails-1.0.xで、Grailsアプリケーションを作成、プロジェクトフォルダへ移動
- grails install-plugin acegi でacegiプラグインをインストール (acegi-0.5.1)
理由:コマンドで簡単にMany-to-ManyなGrailsアプリケーションが作れるから。
- M-to-Mなドメインクラス達を作成 grails create-auth-domains
- データセット用にユーザ管理画面を作成 grails generate-manager
- データの違いが見たいので、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" //ここを変更 } }
- grails run-app で起動して、権限とユーザを追加
- ログインできるか確認
- 動作確認できたら、一応、プロジェクトフォルダを別名で他の所へ保存しておく。(後での確認用)
では、ここから、grails-1.1へアップグレード
内容は、
grails.plugin.location."acegi"="./plugins/acegi-0.5.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:基本受け身です