MyBatis Schema Migrationを使ってみる

この記事は Java Advent Calendar -ja 2010 の4日目のものです。

はじめに

継続的な開発では、データベーススキーマも段階的変化に耐えることが求められる。マイグレーション・システムが必要だ。
そこで、MyBatis Schema Migrationというのがあるらしいので試してみた。ほら、Java屋にはおなじみのMyBatisだ。

インストールする

http://code.google.com/p/mybatis/downloads/list?can=3&q=migrations から、「MyBatis Schema Migrations 3.0.2 GA」をダウンロードし、適当な場所に展開し、PATHを通す。

migrate init - 初期設定

プロジェクトのホームがあれば、その下に空のディレクトリを作り、そこでスキーマの管理をするとしよう。空のディレクトリを作ってcdし、「migrate init」コマンドを実行することで、初期の設定ができる。

cd /some/project/home
mkdir migration
cd migration
migrate init

インストールが上手くいっていれば、下のようなメッセージが表示されるはず。

$ migrate init
Initializing: /some/project/home/migration/.
Creating: environments
Creating: scripts
Creating: drivers
Creating: README
Creating: development.properties
Creating: bootstrap.sql
Creating: 20101216095521_create_changelog.sql
Creating: 20101216095522_first_migration.sql
Done!

上手くいっていない場合、ちゃんとcdしたかなどを疑おう。俺は3回くらいやった。

DB接続情報の設定

JDBCドライバと、接続情報を設定する。ドライバのjarをmigration/driversにコピーし、migration/environment/default.propertiesに接続情報を記述すればよい。

今回は手軽に、H2データベースを使うが、JDBCであれば恐らくなんでも問題はない。

http://www.h2database.com/html/main.html から「Platform-Independent Zip」をダウンロードして展開、JDBCドライバ(bin/h2-1.3.148.jar)をmigration/driversにペーストする。

migration/environment/default.propertiesに設定を記述する。他のDBMSを使う場合は、usernameとpasswordを含めて適当に設定しよう。

driver=org.h2.Driver
url=jdbc:h2:~/migration_test
username=
password=

さて、これで準備が整った。

migrate status - スキーマの状態を確認

migrate statusコマンドにより、スキーマの状態を確認できる。初期状態では、changelogというテーブルを作成する準備が出来ているようだ。もちろん、これがMigrationの管理用テーブルとなる。

$ migrate status
ID             Applied At          Description
================================================================================
20101216095521    ...pending...    create changelog
20101216095522    ...pending...    first migration

「...pending...」とあるのは、未適用状態ということ。とりあえず、適用してみよう。migrate upコマンド。

$ migrate up
========== Applying: 20101216095521_create_changelog.sql =======================
--  Create Changelog
-- Default DDL for changelog table that will keep
-- a record of the migrations that have been run.
-- You can modify this to suit your database before
-- running your first migration.
-- Be sure that ID and DESCRIPTION fields exist in
-- BigInteger and String compatible fields respectively.
CREATE TABLE CHANGELOG (
ID NUMERIC(20,0) NOT NULL,
APPLIED_AT VARCHAR(25) NOT NULL,
DESCRIPTION VARCHAR(255) NOT NULL
)

ALTER TABLE CHANGELOG
ADD CONSTRAINT PK_CHANGELOG
PRIMARY KEY (id)


========== Applying: 20101216095522_first_migration.sql ========================
--  First migration.
-- Migration SQL that makes the change goes here.

migrate statusしてみると、pendingではなくなったらしい:

$ migrate status
ID             Applied At          Description
================================================================================
20101216095521 2010-12-16 19:03:33 create changelog
20101216095522 2010-12-16 19:03:34 first migration

実際のDBの状態を確認すると、changelogというテーブルが作られていて、レコードが2つあることがわかる。
H2の場合、migration/drivers/h2-1.3.148.jarを実行(Finder上でダブルクリックとか)すれば、何となく使えるはず。

migrate new - あらたなバージョンを追加

スキーマを変更したくなった場合、migrate newコマンドを使う。「migrate new "some comment"」のようにコメントを付けると、migration/scriptフォルダ下にsqlファイルの雛形を作ってくれる。

$ migrate new "add table users"
Creating: 20101216101815_add_table_users.sql
Done!

このファイルに対し、進めた場合と戻した場合、両方のスクリプトを記述する。今回はuserテーブルを追加したいということにしよう。戻す場合は、DROPすることになる。

--// add table users
-- Migration SQL that makes the change goes here.

CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    email VARCHAR(255)
);


--//@UNDO
-- SQL to undo the change goes here.
DROP TABLE users;

「migrate status」すると、pendingになっていることがわかるはず。「migrate up」で、スキーマを更新しよう。

$ migrate up
========== Applying: 20101216101815_add_table_users.sql ========================
--  add table user
-- Migration SQL that makes the change goes here.
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(255),
    email VARCHAR(255))

migrate statusしてみると:

$ migrate status
ID             Applied At          Description
================================================================================
20101216095521 2010-12-16 19:03:33 create changelog
20101216095522 2010-12-16 19:03:34 first migration
20101216101815 2010-12-16 19:27:02 add table users

テーブルの追加だけではなく、既存テーブルにカラムを追加したり、カラムの名前を変更するために新規カラム追加→アップデート→既存カラム削除といった、SQLで実現できる程度に複雑な更新も記述できる。システムの設定情報をレコードで管理している場合、設定情報を更新させたり。

migrate version - 特定のバージョンに変更する

さて、スキーマバージョンを戻したくなった。migrate version で、特定のバージョンに変更してくれる。

$ migrate version 20101216095522
Downgrading to: 20101216095522
========== Undoing: 20101216101815_add_table_users.sql =========================
-- @UNDO
-- SQL to undo the change goes here.
DROP TABLE users

statusを確認:

$ migrate status
ID             Applied At          Description
================================================================================
20101216095521 2010-12-16 19:03:33 create changelog
20101216095522 2010-12-16 19:03:34 first migration
20101216101815    ...pending...    add table users

ペンディングに戻った。

ほか、migrate downコマンドでも進めたり戻したりできる。

さて、これで色々できるぞ。

トラブルシュート

ERROR: Could not create SqlRunner. Cause

migrate statusなどをしたとき、↓のようなエラーメッセージが出る場合がある。

ERROR: Could not create SqlRunner. Cause: org.h2.jdbc.JdbcSQLException:
...

H2データベースの場合、ブラウザのコンソール経由で接続しているはずなので、切断すればよい。切断は上部一番左のアイコンで。

その他

  • 既存DBを今から管理したい場合は、テーブル構築スクリプト一式をbootstrapを使うといいらしいぞ。
  • あれ?これってJavaなプロジェクトじゃなくても使えるんじゃねーの?
  • というわけで、Javaとそんなに関係ないけど、最近触ったのでこんな話にしました。

参考