と                           で
DBIx::ClassとDBIx::Class::Schema::Loaderで
楽々O/Rマッピング
        マッピング
WEB技術勉強会 第25回
   技術勉強会    回
RYUICHI TANAKA.
O/Rマッピングとは

オブジェクトとRDBのレコード
を対応付けることができる技術。
SQLを書かなくともDBアクセス
ができる。
代表的ORマッパー
Perl
 DBIx::Class(通称DBIC)
 Class::DBIx(現在は開発停止)
Java
 Hibernate(JPA標準)
Ruby(Rails)
 ActiveRecord
PHP
 Propel( synfonyで使用)
ORマッピングのなにがよいのか

SQLを書かなくて済む
コードがすっきりする
DB構成が変わったときの保守
が比較的楽
逆にORマッピングのだめなところ

処理が遅くなる
複雑なSQLは厳しい
つまり、ORマッピングとは

簡単なSQLですむときに使うと
幸せになれる
それ以外のときは生SQLを実行
しないと幸せになれない
DBIx::Class

 Perlで一番メジャーなORマッ
 パー
 Class::DBIの後継的存在
 Catalystで標準使用されている
DBIx::Class::Schema::Loader

 DBIx::Classで使用するSchema
 ファイルを自動生成する
Schemaファイルとは

 テーブルの各カラムのデータ型
 をオブジェクトとして定義する
 DBIx::Classを継承して定義する
インストール

CPAN経由で
依存モジュールがすごい数イン
ストールされる
Schemaファイルの生成

 ワンライナーの場合
$ perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib -
e 'make_schema_at "Hoge::Schema", {relationships => 1, debug => 1},
["dbi:mysql:hoge","user","password"]'




ただし、今回はワンライナーは使用しない。
ソースファイルにして拡張性を高めて、
Eclipseから実行するため。
Schemaファイルの生成




                ② スキーマファイルが
                   自動生成される


                ① make_schema.pl
                  を実行する
Schemaファイルの生成(コード)
#!/usr/bin/perl
use strict;
use warnings;
use FindBin::libs qw{ export base=syscommon };
use MyLibs::Common::DB::Config;
use DBIx::Class::Schema::Loader qw( make_schema_at );

# スキーマファイルの出力先
my $dump_directory = 'C:/workspace/syscommon';

# データベース名を指定
my $dbname = "tclipers";

my ($conf_obj, $db_conf);

$conf_obj = MyLibs::Common::DB::Config->new();
$conf_obj->use_db("mysql");
$db_conf = $conf_obj->get_db_config();

make_schema_at(
   'MyLibs::Common::DB::Schema',
   {relationships => 1, debug => 1, dump_directory => $dump_directory},
   ["dbi:$db_conf->{dbms}:dbname=$dbname;host=$db_conf->{host}", $db_conf->{user}, $db_conf->{pass}]
);
生成されたSchemaファイル
package MyLibs::Common::DB::Schema::Tclipers;

use strict;
use warnings;

use base 'DBIx::Class';

__PACKAGE__->load_components("Core");
__PACKAGE__->table("tclipers");
__PACKAGE__->add_columns(
 "id",
 { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
 …
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("url_hash_index", ["url_hash"]);


# Created by DBIx::Class::Schema::Loader v0.04006 @ 2009-07-12 01:49:00
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:YCPFZVg0EvGhZEbLwsh2AA


# You can replace this text with custom content, and it will be preserved on regeneration
1;
実際にORマッピングしてみる

Schemaファイル生成時に同時
に作られる「Schema.pm」を
useする
Schema.pmは実行するプログラ
ムから見えるようにSchema
ファイルを生成する必要がある
実行ファイルからSchema.pmが
            離れた位置にある場合は、
Schema.pm
            「FindBin::libs」
            を使って読ませる。

            このやり方は、自作モジュール
            を一括管理するとき便利。


実行ファイル
ORマッピングする前
use TrushCliper::DB;

(中略)

my ($sql, @bind);
my $db = TrushCliper::DB->new();
$db->DBConnect();

$sql = “INSERT INTO tclipers (title, url, comment, date) ”;
$sql.= “VALUES (?,?,?,?)”;
@bind = ($title, $url, $comment, $date);

$db->register($sql, @bind);

$db->Close();
ORマッピングした後
use MyLibs::Common::DB::Config;
use MyLibs::Common::DB::Schema;

(中略)                                                              データベース接続

my $connect_info = ["dbi:$db_conf->{dbms}:dbname=$dbname;host=$db_conf->{host}",
           $db_conf->{user}, $db_conf->{pass}];
my $schema = MyLibs::Common::DB::Schema->connect(@{$connect_info});
$schema->storage->dbh->do("SET names utf8");

my $result = $schema->resultset($schema_name)->find_or_new({
    title => $title,
    url => $url,
    url_hash => $url_hash,
    comment => $comment,
                                                       Insert文と同様
    date => $date
});

unless ($result->in_storage) {
  $result->insert;
}
ORマッピングしてみて

コードはきれいになる
単純なSQLですむときはORMでいいと
思った
学習コストがかかる。ORマッパーごとに
微妙に使い方が違う。
結局工数は大して変わらない気がする
コードをきれいにするだけならストアド
プロシージャでもいい気はする
結論

      時と場所を選べ!
時:単純なSQLな時は使える。複雑な時は使えな
い。
場所:大学なら使い放題。会社はPJ次第…。


技術の理解やリファクタリングなどの目的
では使えるので皆さん使ってみてはどうでしょう?

Web技術勉強会 第25回