Schema::Loaderの利用
第3回
Schema::Loaderを使うべきか
軽いデータベース操作であればSchema::Loaderがお手軽ですが、
●DBIx::Classからデータベースを作成できる
Resultクラスにテーブル定義を書くと、
my $schema =
My::Schema->connect('dbi:SQLite:/path/to/my.db');
$schema->deploy;
とdeployメソッドを使用してデータベースを作成できます。これは特定のデータベース実装に依存しないようにできていますので、
my $schema = My::Schema->connect(
'dbi:mysql:mydb', 'mysql_user', 'mysql_password',
);
$schema->deploy;
これで、CREATE TABLE
が実行され、
●Schemaバージョニング機能が利用できる
Resultクラスにテーブル定義を書くと、
開発を進めていくにつれ、
Schemaバージョニングは、ALTER TABLE
を発行してくれたり、
この機能の詳細はDBIx::Class::Schema::Versionedにまとまっていますので参照してください。
ページャオブジェクト
データベースから取得するデータが多い場合には、
DBIx::Classのsearchメソッドには検索結果と連動したページャオブジェクトを取得できる機能があります。ページャオブジェクトを使用するとWebサイトなどでよく使用するページネーション表示などを簡単に作成できます。
ページャオブジェクトを使用するにはsearchメソッドにrows属性とpage属性を渡します。
my $rs = $schema->resultset('Tweets')->search(
{}, { rows => 10, page => 1, }
);
rows属性には1ページあたりの表示件数を、
my $pager = $rs->pager;
このページャオブジェクトはData::Pageのオブジェクトになっています。
トランザクション
トランザクションをサポートするRDBMSを使用している場合にはDBIx::Classはトランザクションをサポートします。現在DBIx::Classからトランザクションを扱うには次の3つの方法があります。
- txn_
do - txn_
scope_ guard - txn_
begin/ txn_ commit/ txn_ rollback
これらはすべてSchemaオブジェクトのメソッドです。
txn_doを使ったトランザクション
DBIx::Classにおける一番確実なトランザクションの方法は、txn_
メソッドを使用することです。
use Try::Tiny;
my $res;
try {
$res = $schema->txn_do(sub {
# トランザクション処理したい一連の処理
});
} catch {
if ($_ =~ /Rollback failed/) {
# ロールバックに失敗した場合
}
# 何らかのエラーによりロールバックした
}
txn_
にはトランザクションしたい処理をコードリファレンスにして渡します。txn_
はまずトランザクションを開始しその中でコードリファレンスを実行します。そしてその中で何らかのエラーが発生すると自動的にrollbackを発行してくれます。コードリファレンス内で起きた例外はrethrowされるので、
txn_
を使用する注意点として、
txn_scope_guardを使ったトランザクション
より簡単なトランザクションの方法は、txn_
を使用することです。
my $txn_guard = $schema->txn_scope_guard;
# トランザクションしたい一連の処理
$tweet->body("val1");
$tweet->update;
$txn_guard->commit;
これは変数のスコープを利用したトランザクション処理です。DBIx::Classはトランザクションガード変数が生成された場合トランザクション処理を開始し、
txn_
を利用したトランザクションと比べると途中でデータベースとの接続が切れた場合のリトライ機能がないなどの欠点はありますが、
txn_begin/txn_commit/
txn_rollback
txn_
DBIx::Class上でのトランザクションは先述したtxn_
もしくはtxn_
の使用が推奨されていますが、
my $err = '';
try {
$schema->txn_begin;
# トランザクション処理をしたい一連の処理
$schema->txn_commit;
} catch {
$err = $_;
try { $schema->txn_rollback } catch { $err = $_ };
};
die $err if $err; # 必要があれば例外をrethrow
トランザクションの入れ子
現実のアプリケーションコードではまとまった処理ごとに関数などを作成し、
しかし、
UTF-8の扱い
モダンなPerlアプリケーションのベストプラクティスの一つにアプリケーション内部の文字列はすべてUTF-8で扱うというものがあり、
このような場合は、
# SQLiteの場合
My::Schema->connect(
'dbi:SQLite:/path/to/database.db', '', '', {
sqlite_unicode => 1,
},
);
# My SQLの場合
My::Schema->connect(
'dbi:mysql:database', 'db_user', 'db_password', {
on_connect_do => ['SET NAMES utf8'],
mysql_enable_utf8 => 1,
}
);
# Postgre SQLの場合
My::Schema->connect(
'dbi:Pg:database', 'db_user', 'db_password', {
pg_enable_utf8 => 1,
}
);
デバッグ
DBIC_TRACE環境変数
DBIx::Classを使用していると、
$ DBIC_TRACE=1 perl your_app.pl
また次のようにファイル名を指定することで、
$ DBIC_TRACE="1=/path/to/trace.txt" perl your_app.pl
SQLクエリのプロファイリング
DBIC_
My::Schema->storage->debugobj(My::Profiler->new);
こうすることでDBIC_
またこの機能を使用したSQLプロファイリングモジュールとしてDBIx::Class::QueryLogというモジュールもあります。