内容へ移動
Cat Paw Software
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
トレース:
•
rvm
•
php
•
ios
perl:dbic
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== DBIx::Class ====== [[http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/Manual.pod|DBIx::Class(DBIC)]] はPerlのデータアクセスライブラリ ===== インストール ===== CPANインストール DBICをCPANでインストール * DBI * DBD::mysql * DBIx::Class * DBIx::Class::Schema::Loader ''DBIx::Class::Schema::Loader''を入れれば、その上の3つもインストールされる。DBDはどれを使うか聞かれるがデフォルトは「インストールしない」なので必要と思うならば連打しないように注意。DBD::*は後からインストールしても問題ない。 大量の依存パッケージをインストールするので未読のRSSでも読みながら気長に待ちましょう。 ===== 使い方 ===== ==== 準備 ==== まずMySQLにテーブルを作る <code sql> create table article ( id BIGINT AUTO INCREMENT NOT NULL, author_id BIGINT NOT NULL, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, written_at DATETIME NOT NULL, PRIMARY KEY(id), FOREIGN KEY(category_id) REFERENCES author (id) ON DELETE RESTRICT ON UPDATE RESTRICT ); create table author ( id BIGINT AUTO INCREMENT NOT NULL, name BIGINT NOT NULL, PRIMARY KEY(id), ); </code> Blog::Schema.pm を作成 <code perl> use strict; use warnings; package Blog::Schema; use base "DBIx::Class::Schema::Loader"; __PACKAGE__->loader_options( debug => 1, components => ["InflateColumn::DateTime"] ) </code> debugはデバッグログを標準エラーに書き出す。components => ["InflateColumn::DateTime"] は[[#InflateColumn::DateTime|datetime型カラムをPerlのDateTimeクラスにマッピング]]するための設定。 DBICでデータアクセスするには、テーブルのスキーマクラスを作成する必要がある。これにはテーブルのカラム情報などが記述されるが、俺はDRY野郎なのでDDLで一度記述した情報をPerlでまた書くなんて面倒である。そこで DBIx::Class::Schema::Loader を Blog::Schema の親クラスにすると、スキーマクラスをデータベースの情報から実行時に動的生成する。この場合、Blog::Schema::Article と Blog::Schema::Author というクラスが生成されている。 ==== 使ってみる ==== <code perl> $schema = Blog::Schema->connect("dbi:mysql:test", "user", "password", { mysql_enable_utf8 => 1, on_connect_do => ["SET NAMES utf8"] }); # DBIx::Class::ResultSet の取得 $resultset = $schema->resultset("Article"); # リストコンテキストでsearchを実行すると DBIx::Class::Row の配列が取得される @articles = $resultset->search("author_id" => 1); # スカラコンテキストでsearchを実行すると検索条件を設定して DBIx::Class::ResultSet(自分自身)を返す、SQLは遅延実行される。 $articles = $resultset->search("author_id" => 2); # 最初のレコードを取る $articles->first; # レコードに順番にアクセス binmode STDOUT, ":utf8"; while($article = $articles->next) { print($article->title); } </code> connectで接続する * ''mysql_enable_utf8''は文字列のデータ保存時にutf8フラグを落とし、データ取り出し時にutf8フラグを立てるオプション。まだ試験実装らしいがみんな気にせず本番に使ってる。 * ''on_connect_do''は接続時に実行するクエリを設定するもの。文字化けしないようにおなじみ''SET NAMES utf8''を実行させる。 resultsetで指定するテーブル名先頭が大文字になっているので注意。ここで指定するのはテーブル名ではなく、スキーマクラスの ''Blog::Schema::Article'' から、''Blog::Schema''を除いた名前である。 なお draft_item のようにテーブル名にアンダースコアがある場合は、''Blog::Schema::DraftItems'' というクラス名になる。 ===== InflateColumn::DateTime ===== DBのdatetime型をPerlのDateTimeオブジェクトを相互に自動変換することができる。 ==== インストール ==== 最新のDBICではDBIx::Class::InflateColumn::DateTimeがコアコンポーネントとなっているのでプラグインは不要だが、DateTimeとFormatterが必要。以下の2つのモジュールをCPANからインストールする。 * DateTime * DateTime::Format::MySQL ==== 設定 ==== スキーマクラスのcomponentsに設定を追加する。 <code perl> use strict; use warnings; package Blog::Schema; use base "DBIx::Class::Schema::Loader"; __PACKAGE__->loader_options( debug => 1, components => ["InflateColumn::DateTime"] ) </code> これでdatetimeカラムやtimestampカラムにDateTimeオブジェクトをセットしたり、DateTimeオブジェクトで取得したりできるようになる。 ===== SQLログ ===== 環境変数、''DBIC_TRACE=1'' をセットするコンソールにSQLログ出力する。ファイル名を指定するとファイルに書き出す。 DBIC_TRACE "=/tmp/sql.log" 環境変数''DBIX_CLASS_STORAGE_DBI_DEBUG''でも同じらしい(詳細不明…) ===== リレーションの設定 ===== DBIx::Class::Schema::Loaderは外部キー制約を見てリレーションも設定してくれるが、アクセサメソッドのネーミングセンスがイマイチなので自分で設定する。自動設定させたいならloader_optionsで relationships => 1 とする。 ==== リレーション設定を書く ==== リレーションだけ自分で設定する場合は、動的生成されるスキーマクラスにリレーションだけ自分で記述すればいい。Schema::Loaderを使った場合は基本は自動生成で差分を自分で記述することができる。 先のテーブル設定では Blog::Schema::Author と Blog::Schema::Article というスキーマクラスが動的生成されるので、Blog/Schema/Author.pmとBlog/Schema/Article.pm ファイルを自分で作成してリレーション設定を記述。 <code perl> # Blog/Schema/Author.pm package Blog::Schema::Author; __PACKAGE__->has_many("articles", "Blog::Schema::Article", "author_id"); </code> アクセサメソッド名, リレーション先のクラス, 相手の外部キー名(参照されるインデックスがプライマリキーの場合はその記述を省略可能) <code perl> # Blog/Schema/Article.pm package Blog::Schema::Article; __PACKAGE__->belongs_to("author", "Blog::Schema::Author", "author_id"); </code> アクセサメソッド名, リレーション先のクラス, 外部キー名(参照先のインデックスがプライマリキーの場合はその記述を省略可能) ==== 使い方の例 ==== <code perl> $author_name = $schema->resultset("Article")->find(1)->author->name; $rs_authors = $schema->resultset("Author")->search({"name" => {"like" => "あ%"}}); while(my $author = $rs_authors->next) { print($author->name); print($author->articles->first->title); } </code> ==== プリフェッチ ==== 一対一、多対一リレーションのときは、最初のSQLのときに予めリレーションテーブルのデータも取得できる。 <code perl> my $beginning_of_year = DateTime->today(time_zone => "local")->set(month => 1, day => 1); my @results = $schema->resultset("article")->search({ written_at => { ">" => $beginning_of_year } },{ prefetch => "author" }); while( @results ) { print $_->title, "\n"; print $_->author->name, "\n"; } </code> ===== search_literalの条件とハッシュによる普通のsearch条件を同時に指定 ===== search_literalを使えばSQLのwhere句を自在に書けるが、search_literalによる指定とハッシュによる普通のsearch条件と混在させたい場合。 Itemが1つ以上存在するCategoryで、CategoryのID <code perl> my %where; my %param; $where{ id } = { ">" => $id } $where{ name } = { -like => $name . "%" }; $param{ order_by } = "me.name"; $where{ -and } = "EXISTS (SELECT 1 FROM items WHERE items.category_id = me.id AND items.attribute = ? AND items.name like ?)"; $param{ bind } = [ 100, "%Perl%"]; my @results = $schema->resultset("Categories")->search(\%where, \%param); </code> 生成SQLは… <code sql> SELECT ....(省略).... FROM categories me WHERE (id = ? AND name like = ? AND (EXISTS (SELECT 1 FROM items WHERE items.category_id = me.id AND items.attribute = ? AND items.name like ?))) ORDER_BY me.name; </code> bindというキーでサブクエリのバインド変数を指定しているが、これはソースを読んで見つけた方法なのでバージョンが違うと動作しないかもしれない(調べたDBIx::Classのバージョンは0.08007)
perl/dbic.txt
· 最終更新: 2010/01/17 14:10 by
127.0.0.1
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ