S2JDBC-Genの紹介 その6 − マイグレーション
S2JDBC-GenのマイグレーションはRailsのマイグレーションとは違います。Railsのマイグレーションはバージョン間のスキーマの変更分のみを適用しますが、S2JDBC-GenはDROP&CREATEで一旦全部消してから作り直すというスタンスです(データはダンプしてロード)。
運用がはじまったら「一旦全部消してから作り直す」というのはできませんが、開発中はこっちのほうがわかりやすいんじゃないかと思います。S2JDBC-Genは開発に主眼を置いています。
Railsのmigrationで、開発時は変更履歴が不要という意見があるようですね。
migration の問題
マイグレーション
マイグレーションはmigrateというAntタスクで行います。前回、SCHEMA_INFOというテーブルとddl-info.txtというファイルでそれぞれバージョンを管理しているといいました。簡単に説明します。
SCHEMA_INFOテーブル
これはデータベースのスキーマのバージョンを管理するテーブルです。ここで管理されるバージョン番号はマイグレーション元のバージョン番号になります。migrateをすると新しいバージョン番号で更新されます。
ddl-info.txtファイル
これはエンティティやエンティティから生成されたDDLのバージョンを管理するファイルです。ここで管理されるバージョン番号はマイグレーション先のバージョン番号になります。gen-ddlすると番号が更新されます。
S2JDBC-Genのマイグレーションは、SCHEMA_INFOテーブルのバージョン番号でスキーマをDROPしてddl-info.txtのバージョン番号でスキーマをCREATEします。バージョン番号は、DDLを管理するディレクトリの名前に対応します。DDLを管理するディレクトリがどんなものかというとこんなものです。
バージョン番号 1 から 2 へのマイグレーションが行われる場合は、db/migrate/0001/dropの下のDDLでスキーマを削除した後、db/migrate/0002/createの下のDDLでスキーマを再作成します(CSVがあればデータのロードも行います)。
シナリオ例
シナリオで考えてみるとイメージしやすいと思います。前提として、次の条件が成り立っているものとします。
- ソースコードやDDLはSubversionで管理されている
- 開発用のDBは各開発者のPCにそれぞれインストールされている
シナリオは次のようなものです。今、Subversionのtrunkのddl-info.txtで管理されているバージョン番号も、各開発者のDBに含まれるSCHEMA_INFOテーブルのバージョン番号も 1 だとします。
- Aさんがエンティティにプロパティを追加して、gen-ddlします。このとき、ddl-info.txtのバージョン番号が 1 から 2 に更新されます。
- Aさんは自分の環境でmigrateして自分のデータベーススキーマにエンティティの変更を反映させます(テーブルにカラムを追加します)。このとき、SCHEMA_INFOのバージョン番号は 1 から 2 に更新されます。
- Aさんは、migrateが成功し、その後のテストも成功することを確認したら、Subversionにエンティティのjavaファイル、生成したDDL、ddl-info.txtをコミットします。Aさんの作業はひとまずこれで終わりです。
- BさんはSubversionから最新データを取得します。このときBさんのSCHEMA_INFOのバージョン番号はまだ 1 ですが、ddl-info.txtはAさんが更新したものを取得しているのでバージョン番号はすでに 2 になっています。
- BさんはDDLが変更されていることに気づいたらmigrateを実行します。すると、SCHEMA_INFOのバージョン番号 1 でDROP、ddl-info.txtのバージョン番号 2 でCREATEが行われ、Bさんの開発用DBも最新のスキーマになります。このとき、SCHEMA_INFOのバージョン番号も 1 から 2 に更新されます。
このシナリオは、最新のバージョンへのマイグレーションを行うものですが、もちろん特定のバージョンを指定したマイグレーションを行うこともできます。
ファイル内の任意のSQLを実行するタスク
これで、S2JDBC-Genのだいたいの機能は紹介できました。細かいところはいろいろありますけど。
次回はファイルに記述された任意のSQLを実行するタスクを紹介します。SQLのステートメントだけでなく、Transact-SQLやPL/SQLのようなSQLのブロックも実行できるので便利じゃないかと思います。migrateタスクの内部で使っている機能ですが、単独のタスクとしても使えるのでちょっとしたユーティリティとして使ってもらえればと思います。