チームで開発を行っているとき、DBスキーマの変更で苦労したことがあるのではないでしょうか。
DBを変更したけど、それを知らない他のメンバーの環境と不整合が生じてしまったりすることもあるので、各メンバ(または複数のマシン)でDBスキーマを統一することは重要です。
PlayはRDBMSのスキーマ遍歴を追跡する方法を持っており、上記のようなケースで有用です。この章ではEvolutionsを使用してDBスキーマを更新してみましょう。
Evolutionsは、「Evolutionスクリプト」を使用することで、DBの変更を追跡します。このスクリプトは一定のルールに従ってSQLを記述するファイルです。デフォルトのDBに対してEvolutionスクリプトを実行したい場合、conf/evolutions/defaultディレクトリにスクリプトを保存します。
スクリプトファイルに付ける名前は決められており、最初のスクリプトは1.sql、2番目のスクリプトは2.sqlというふうに、数値を順番に付けていかなければなりません。
スクリプトファイルの内容は、次のようになっています。
# --- !Ups create table foo ( id int(10) not null auto_increment, name varchar(100), primary key(id)); alter table bar add newColumn varchar(10); # --- !Downs drop table foo; alter table bar drop newColumn;
Evolutionスクリプトは2つの部分で構成されています。「# --- !Ups」と書いてある部分からは、スキーマの変更内容を記述します。「# --- !Downs」と書いてある部分からは、Ups部分の変更を元に戻すための記述します。
UpsもDownsも、上記のようにコメントで区切らなければいけません。
また、次の条件を満たす場合、Evolution設定が自動で有効化されます。
もしEvolutionを無効化したい場合、conf/application.confで、下記設定を追加してください。
evolutionplugin=disabled
開発モードでは、Evolutionが有効化されているとき、スキーマの状態はリクエストごとにチェックされます。その際にスキーマが最新状態でないと判断された場合、SQLを実行してスキーマを更新させるように促すページがブラウザに表示されます。
※本番モードの場合、アプリケーション起動前にスキーマがチェックされます
では、Evolutionsを使用して、スキーマの更新をしてみましょう。まずはユーザー情報を管理するテーブルを作成します。conf/evolutions/defaultディレクトリに、「1.sql」という名前で次のようなファイルを置きましょう。
# --- !Ups create table User ( id int(10) not null auto_increment, name varchar(100), email varchar(100), password varchar(100), createDate timestamp default current_timestamp(), primary key(id)); # --- !Downs drop table User;
Playコンソールでアプリを起動し、「http://localhost:9000」にアクセスしてみましょう。次のような、Evolutionスクリプトを実行するように促すページが表示されます。
「Apply this script now!」と記述されたボタンを押すと、1.sqlの内容が実行されてスキーマが最新状態になります。mysqlのコンソールで確認してみると、Userテーブルが作成されているのが分かります。
なお、「play_evolutions」という名前のテーブルも作成されています。これはEvolutionsがスキーマを管理するために使用するテーブルです。
続けて、ユーザーがポストしたデータを管理するテーブルを作成します。2.sqlを次の内容で作成し、conf/evolutions/defaultディレクトリに置きましょう。
# --- !Ups create table Post ( id int(10) not null auto_increment, userId int(10) not null, title varchar(100) not null, body text, createDate timestamp default current_timestamp(), primary key(id), foreign key(userId) references USer(id) ); # --- !Downs drop table Post;
「http://localhost:9000」にアクセスすると、先ほどと同じくEvolutionスクリプトの実行を促すページが表示されるので、スクリプトを実行しましょう。UserテーブルとPostテーブルができたら、準備は完了です。
この章でやってきたように、Evolutions機能を使用することで、スキーマの状態を手軽に同期させることができます。Evolutionsについての詳細は、公式サイトの「Documentation: Evolutions ― Playframework」でも確認可能です。
Play2では、DBにアクセスするための方法は特に決まっていません。バンドルされている「Anorm」というライブラリを使用したり、「Slick」などのサードパーティ製ライブラリを使用することもできます(Play2-Javaでは、「EBean」というORMの使用が可能です)。
本章では、Anormを使用して、Play2でのDBアクセスを行ってみましょう。
まずは、PlayでDBアクセスを使用する方法について解説します。DBアクセスをするには、play.api.dbパッケージのDBクラスを使用してデータソースやコネクションを取得します。
import play.api.db._ ・ ・ ・ //データソース取得 val ds = DB.getDataSource() //コネクション取得 val con = DB.getConnection()
上記手法でデータソースやコネクションを取得できますが、使い終わった後は自分でclose()関数を呼び出す必要があります。なので、下記のような記述を用いてDBにアクセスするのが推奨されています。
//defaultデータベースにアクセス DB.withConnection { implicit conn => // DBアクセス処理 }
ブロック内の処理を抜けると、ConnectionとともにStatement、ResultSetもcloseされます。また、default以外のDBを指定したい場合、withConnectionの第1引数で指定します。
さらに、withTransaction関数を使用することで、ブロックの処理を1つのトランザクションとさせることができます。
DB.withTransaction { implicit conn => // このブロックの処理は1つのトランザクションとなります }
さて、コネクションの扱い方は分かったので、Anormについて解説をしましょう。
Anormを使用すると、SQLをそのまま使用してDBにアクセスできます。さらに、結果データをパースするための機能も持っています。この説明から分かるように、AnormはORMではありません。DBにアクセスするためにDSLは一切必要なく、SQLをそのまま使用します。
また、AnormはJDBCデータをScalaのデータ構造へ変換するためのAPIを提供してくれます。
Anormは既存のDBライブラリと比較すると、ちょっと取っ付きにくい部分があるかもしれませんが、AnormのAPIをScalaから使用することで、SQLの実行や取得したデータセットのパース処理をシンプルかつ柔軟に記述可能です。
次ページでは、基本的なAnormの使用方法を見てみましょう。
Copyright © ITmedia, Inc. All Rights Reserved.