LiquiBaseメモ
昨年秋のJGGUG合宿でもくもくと調べた結果のメモです。今さらですがまとめておきます。
日本語チュートリアル
DBAを救え! DBリファクタリングツール「LiquiBase」を使ってみよう
http://news.mynavi.jp/articles/2007/10/25/liquibase/index.html
ちょっと古いが、チュートリアルとしてはよい記事だと思います。
ChangeSetに指定できるタグのリスト
LiquiBase Extension
LiquiBase Extension Portalに集約されているようです。
https://liquibase.jira.com/wiki/display/CONTRIB/LiquiBase+Extensions+Portal
公式Wikiからのリンクが切れているので、こちらを見てください。
LiquiBase JIRA
ToDo: Groovy DSL
Liquibaseはマイグレーション定義をXMLで記述しますが、Groovyで記述できるようにするためのDSLがあります。ドキュメントが少ないので、使い方から調べる必要がありますね。。。
https://github.com/tlberglund/groovy-liquibase
Grails Database Reverse Engineering Plugin - G* Advent Calendar 2012 -
G* Advent Calender 2012の12/6担当、@nobusue です。
どうも風邪を引いたらしく、体調がやばい事になってます。。。ということで、JGGUG合宿2012の成果まとめで勘弁してください。
Grailsは通常、モデルオブジェクトを作成し、そこからRDB(もしくはKVSなど任意のデータストア)にデータを永続化するという手順で利用します。しかしながら、既存のRDBがあり、そのデータを管理するUIをささっと作りたいというお話は割りとよく聞きます。
そんなときに便利なのが、Database Reverse Engineering Pluginです。
http://grails-plugins.github.com/grails-db-reverse-engineer/
ただ、こいつはちょっと癖があるので、使いこなすにはいくつかコツが必要です。ここでは、私が踏んだ地雷を公表しておきたいと思います。
Pluginのインストール
適当な新規Grailsアプリケーションを作成します。ここでは仮にtestとしました。
Grailsは2.1.1、Database Reverse Engineering Pluginは0.4で動作確認しています。
次に、次のコマンドでPluginをインストールします。
nobusue-MacBookPro:test nobusue$ grails install-plugin db-reverse-engineer Plugin installed.
無事にインストールできました。そう、インストールはね。。。
DBの準備
今回はMySQL5を利用しました。みなさんのお手元では適当なDBを作成してください。(もちろんですがGrailsがサポート対応しているものにしてくださいね!)
データを自分で作るのが面倒だったので、MySQLのサイトで公開されているサンプルデータを利用させていただきました。このデータ、MySQLの記述検定にも使われているそうなので、一度見ておくとよいかもです。
http://dev.mysql.com/doc/index-other.html
今回はDB=worldにworld.sqlを取り込みました。
データソース設定
Grailsのデータソースを設定します。
[grails-app/conf/DataSource.groovy]
dataSource { url = 'jdbc:mysql://localhost/world' driverClassName = 'com.mysql.jdbc.Driver' username = 'root' password = 'password' dialect = org.hibernate.dialect.MySQL5InnoDBDialect }
あと、PluginがJDBCドライバを参照できるように、依存関係を追加してやります。
[grails-app/conf/BuildConfig.groovy]
dependencies { runtime 'mysql:mysql-connector-java:5.1.20' }
最後に、Plugin自体の設定を追加します。
[grails-app/conf/Config.groovy]
grails.plugin.reveng.jdbcDriverJarDep ='mysql:mysql-connector-java:5.1.20'
DB Reverse Engineering Plugin実行
さあ、これで準備完了です。DBサーバーが起動していることを確認して、Pluginを実行してみましょう!
nobusue-MacBookPro:test nobusue$ grails db-reverse-engineer --stacktrace Compiling 10 source files.| Error Error executing script DbReverseEngineer: : Compilation Failed (NOTE: Stack trace has been filtered. Use --verbose to see entire trace.) : Compilation Failed at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291) at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106) at DbReverseEngineer$_run_closure1.doCall(DbReverseEngineer:51) Caused by: java.lang.IllegalArgumentException: The includeAntRuntime=false option is not compatible with fork=false ... 3 more Error Error executing script DbReverseEngineer: : Compilation Failed
ということで、残念ながらPluginの実行が失敗します。どうもモデルオブジェクトの自動生成あたりで引っかかっている雰囲気ですが、細かいことを追求するのはやめておいて、ドキュメントにしたがってGrailsとPluginのバージョンを下げてみます。
改めて環境構築
ドキュメントによると、「Grails2.0+Plugin0.4で動かない場合は、いったんGrails1.3+Plugin0.3でモデルオブジェクトを生成し、そのアプリケーションをGrails2.0の環境にマイグレーションしろ」と書いてありました。もっと分かりやすいとこに書いといてくれよ。。。
ということで、Grails1.3.9をインストールし、再びアプリケーションを作成します。
Reverse Engeering PluginがMaven Centralを参照するのですが、Grails1.3のテンプレートでは無効化されているのでリポジトリを追加します。
[grails-app/conf/BuildConfig.groovy]
repositories { mavenLocal() mavenCentral()
Pluginのインストール時はバージョン指定をお忘れなく。
grails install-plugin db-reverse-engineer 0.3
grails-app/conf/Config.groovy および grails-app/conf/DataSource.groovy は、Grails2.0のときと同様に修正します。
改めてDB Reverse Engineering Plugin実行
> grails db-reverse-engineer Running script /Users/nobusue/.grails/1.3.9/projects/test13/plugins/db-reverse-engineer-0.3/scripts/DbReverseEngineer.groovy Environment set to development [copy] Copied 3 empty directories to 1 empty directory under /Users/nobusue/.grails/1.3.9/projects/test13/resources [copy] Copying 1 file to /Users/nobusue/.grails/1.3.9/projects/test13/resources [copy] Copied 3 empty directories to 2 empty directories under /Users/nobusue/.grails/1.3.9/projects/test13/resources [mkdir] Created dir: /Users/nobusue/.grails/1.3.9/projects/test13/plugin-classes [groovyc] Compiling 13 source files to /Users/nobusue/.grails/1.3.9/projects/test13/plugin-classes [mkdir] Created dir: /Users/nobusue/work/grails/test13/target/classes [groovyc] Compiling 7 source files to /Users/nobusue/work/grails/test13/target/classes [mkdir] Created dir: /Users/nobusue/.grails/1.3.9/projects/test13/resources/grails-app/i18n [native2ascii] Converting 13 files from /Users/nobusue/work/grails/test13/grails-app/i18n to /Users/nobusue/.grails/1.3.9/projects/test13/resources/grails-app/i18n [copy] Copying 1 file to /Users/nobusue/work/grails/test13/target/classes [copy] Copied 2 empty directories to 2 empty directories under /Users/nobusue/.grails/1.3.9/projects/test13/resources [echo] Starting database reverse engineering, connecting to 'jdbc:mysql://localhost/world' as 'root' ... [echo] Finished database reverse engineering
おおっ、無事に City.groovy, Country.groovy, CountryLanguage.groovy が生成されました。CountryLanguageは複合キーが定義されているため、hashCode()も自動生成されています。すばらしい。
UI作成
モデルオブジェクトさえ手に入ればこっちのもの。試しにscaffoldして動かしてみます。
grails generate-all xxx.City
すると、scaffoldは問題なく終了しますが、生成されたUIを実行するとエラーが出てしまいます。原因はMySQLのテーブル"CountryCode"がフィールド"String countryCode"にマッピングされており、これを改めてGORMに通すとCOUNTRY_CODEをさしてしまうためでした。
対策としては、モデルオブジェクトにmappingを追加するか、フィールド名をcountrycodeのようにcamel caseでないものに修正する必要があります。今回は後者の対応で対応することで、めでたくUIから操作できるようになりました。
次にCountryですが、mapping追加でviewから操作することはできました。
static mapping = { id name: "code", generator: "assigned" version false surfaceArea column: "surfacearea" indepYear column: "indepyear" lifeExpectancy column: "lifeexpectancy" localName column: "localname" governmentForm column: "governmentform" headOfState column: "headofstate" }
しかし、UI上ではリスト表示の際にID列がないため、editのリンクが機能しません。
同じく、CountryLanguageはテーブル名がcamel caseになるので、こちらもmappingを修正して対応します。
static mapping = { table "countrylanguage" id composite: ["countryCode", "language"] version false countryCode column: "countrycode" isOfficial column: "isOfficial" }
ここで気づいたのが、idはマッピングされているのに、scaffoldで生成したviewのID列には表示されていないということ。何か対策があるんでしょうが、調べ切れていないのでとりあえず宿題ということにさせてください。
あと、元のテーブルにはリレーションが設定されているのですが、モデルオブジェクトの関連には反映されていないですね。Pluginの実行時に何か設定が必要なのでしょうか?
まとめ
ちょっと癖のあるDB Reverse Engineering Pluginですが、ベースとなっているHibernate Toolsのことを理解していればもうちょっと使いこなせるかもしれないです。素直なテーブルなら使えると思いますので、ぜひお試しください。(そしてレポートを。。。)
追記
2012/12/6現在でReverse Engineering Plugin 0.5がリリースされてました。。。こちらも確認せねば。。。
次は @nobeans さんです!
継続的デリバリー読書会#5に参加 / DBマイグレーションツール
@kyon_mm さん主催の読書会も第五回になりました。
今回の対象範囲は
- 第10章 アプリケーションをデプロイ・リリースする
- 第11章 基盤と環境を管理する
- 第12章 データと管理する
でした。どの章も本業と関わりが深く、参加されたみなさんとのディスカッションでもいろいろと考えさせられることが多くありました。
個人的には、過去に参加したプロジェクト(開発者20人くらい)で「刻々と変化するDBスキーマとアプリの整合性をどうやって維持するか」という作業に悩まされた経験から、第12章の内容が非常に示唆に富んでいました。ここは今後も掘り下げていきたいと思っていますが、忘れてしまう前に現時点での自分なりの見解をまとめておきます。
マイグレーション用SQLを直接書くケース
MyBatis Schema Migrationsがよさそう。@kyon_mm さんが実際にプロジェクトで利用しているそうです。
http://code.google.com/p/mybatis/wiki/Migration
SQLを直接書けるので柔軟性が高いのがメリットですが、マイグレーションスクリプトがDB依存になってしまうことや、アプリケーション側(Java系言語想定)との対応関係が見えづらくなってしまうことが課題ではあります。
書籍ではDbDeployというツールを紹介していますが、これよりもMyBatis Schema Migrationsの方が高機能かつ活発にメンテされているようですね。
マイグレーション用SQLを直接書かないケース
DBに依存しない何らかの定義ファイルやドメインオブジェクトをベースにマイグレーションを記述する手法になるかと思います。
ER定義をベースとするタイプでは、Jiemamyが使えそうです。(最近滞っているようですが。。。)
http://jiemamy.org/display/PORTAL/Home
ドメインオブジェクトをベースにするタイプはRailsのmigrationが先駆者だと思うのですが、Java系であればGrailsのモデルオブジェクト(GORM)を利用するというアイデアがあります。実際にどこまで使えるかはこれから検証したいと思いますが、既存のDBスキーマからリバースでモデルを生成し、それをGrailsのmigration pluginで扱うことができればSQLレスのマイグレーションができるかも、という話です。
http://grails-plugins.github.com/grails-db-reverse-engineer/
http://grails-plugins.github.com/grails-database-migration/
QUMIのモバイルプロジェクター購入しました
こちらの記事に触発されてAmazonでぽちってしまいました。
http://itlifehack.jp/archives/6478870.html
現物はこちら。比較のために「継続的デリバリー」と重ねてみました。
こんなに小さいボディなのに、解像度は1280x800、かつ数m先の壁に映しても文字が読める明るさです。
カメラ用三脚で固定もでき、台形補正もできるので、ちょっとした打ち合わせや勉強会などで活用できそうですね。超おすすめの商品です。
- 出版社/メーカー: VIVITEK
- 発売日: 2011/10/11
- メディア: Personal Computers
- 購入: 1人 クリック: 71回
- この商品を含むブログ (3件) を見る
Vim(GVim)でGitのコミットログを書く設定
msysgitを使う場合です。Git-1.7.7.1-preview20111027.exeで動作確認しています。GitHubなどとの連携を考慮して、コミットログはutf-8で記録することを前提とします。
etc/inputrc
# disable/enable 8bit input #set meta-flag on #set input-meta on #set output-meta off #set convert-meta on set convert-meta off set meta-flag on set output-meta on set kanji-code utf-8
etc/profile
export GIT_PAGER="nkf -s | LESSCHARSET=utf-8 less" export GIT_EDITOR="'/C/ap/vim73-kaoriya-win64/gvim.exe' -c 'set fenc=utf-8'"
コミットログのエディタはKaoriya版を使っています。set fencしているのがミソで、これがないとコミットログ編集時のデフォルトがutf-8になりませんのでご注意を。
Windows用のnkfはこのへんから入手できます。古いバージョンだとutf-8に対応してなかったりするのでご注意を。
utf-8でないコミットログを記録してgit commit --amendで上書きする場合、既に記録済みのコミットログのエンコーディングでGVimがファイルを開きますので、明示的にutf-8に修正してからコミットしてやる必要があります。(自分はこれでちょっと悩みました。。。)
2011年09月05日のツイート
@nobusue: なによりも、たった100ページで一通りの使い方が説明できること自体、Gradleのシンプルさを証明していると思う。 #gradle_book
2011-09-05 02:02:53 via web
@nobusue: 特に、Mavenの弱点である階層化プロジェクトのビルドを、Gradleでは効率よく処理することができる。これが理由でGradleに移行している大物OSSプロジェクトが多いらしい。
2011-09-05 01:57:50 via web
@nobusue: GradleはMaven同様オブジェクトモデルをベースとしたビルドプロセスを構築するアーキテクチャを採用しているが、GroovyもしくはGroovyベースのDSLによるオブジェクト操作が可能であり、柔軟な制御が容易である。
2011-09-05 01:56:11 via web
@nobusue: Mavenはオブジェクトモデル(POM)ありきで設計されていて、その枠組みの中で使うのには便利だが、POMから外れることをしようとすると非常に困難になる。一方、Antのビルド定義はプリミティブな操作を積み上げていく必要があり、複雑なビルドプロセスを表現するにはシンプルすぎる。
2011-09-05 01:54:33 via web
@nobusue: オライリーの #gradle_book 読了。約100ページと読みやすく、AntやMavenからの移行(共存)についての記述もあり入りやすい。Gradleはプロダクトの立ち位置が非常にGroovy的で、Antの自由度とMavenのCoCのいいとこどりを実現している。
2011-09-05 01:50:15 via web
@nobusue: 佐賀Groovy勉強会 - [PARTAKE] #groovy_saga URL via @partakein