ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~ Hirobanex(Akabane Hiroyuki) 2012-06-29@Perl Beginners #3 コンテンツ • Tengを使いたい3つの理由 • ビギナーにオススメのTengの導入方法 • 本来のO/Rマッパーの効用 1 Tengを使いたい3つの理由 • DBIはよくわからん • O/Rマッパーだと開発が抜群に早くなる • コード量が少ないし、勉強になる 2 生DBIはよくわからん • コンストラクション時の設定って? • セレクト系メソッドどれ使えばいい? • ドキュメントが長すぎてどこ読めば? • トランザクションって? • 突然、コネクション切れる? 3 セレクト系メソッドどれ使えばいい? refとかarrayとかhashとか、頭がパンクします・・・ •fetchrow_arrayref •fetchrow_array •fetchrow_hashref •fetchall_arrayref •fetchall_hashref •selectrow_array •selectrow_arrayref •selectrow_hashref •selectall_arrayref •selectall_hashref •selectcol_arrayref 4 O/Rマッパーだと開発が抜群に早くなる 複数データ群をリレーションつけて登録する場合のコード比較 use DBI; DBI #Teng-0.14_05 use DBI; use Teng; use Teng::Schema::Loader; my @data_set = ( [26,'hiro'], [27,'bane'], ); my $dbh = DBI->connect("DBI:mysql:db_name;", "root", "pass",{ AutoCommit => 0, }); Teng my @data_set = ( [26,'hiro'], [27,'bane'], ); my $dbh = DBI->connect("DBI:mysql:db_name;", "root", "pass",); for my $data (@data_set) { my ($age,$name) = @$data; my $teng = Teng::Schema::Loader->load( dbh => $dbh, namespace => 'MyAPP::DB', ); $teng->load_plugin('FindOrCreate'); my ($age_id) = $dbh->selectrow_array(q{ SELECT id FROM age WHERE age = ? },undef,$age); unless ($age_id) { my $sth = $dbh->prepare(q{ INSERT INTO age (age) VALUES ( ? ) }); $sth->execute($age); my $txn = $teng->txn_scope; for my $data (@data_set) { my ($age,$name) = @$data; my $row = $teng->find_or_create('age',{ age => $age }); #mysql限定 $age_id = $dbh->last_insert_id(undef, undef, 'age', 'id'); } my $sth = $dbh->prepare(q{ INSERT INTO user (age_id, name) VALUES (?, ?) }); $sth->execute($age_id, $name); } $dbh->do('COMMIT'); 20行 $teng->insert('user', { age_id => $row->id, name => $name }); } $txn->commit; 7行 5 コード量が少ないし、勉強になる • オーサーは日本人のnekokakさん • 不明点は誰かに聞けばわかりそう • 日本語情報豊富 • 挙動確認がコード量が少ないため楽 • コードをおうと、Perlの勉強になる 6 ビギナーにオススメのTengの導入方法 DBIもよくわからんけど、とにかく早く使ってみたい人向け • Tengのnew(オブジェクトの作り方) • SELECT • INSERT、UPDATE、DELETE • トランザクション 7 Tengのnew(オブジェクトの作り方) Teng::Schema::Loaderというのを使うと楽 #Teng-0.14_05 use strict; use warnings; use DBI; use utf8; use Teng; use Teng::Schema::Loader; とりあえずメソッド化 sub teng { my $dbh = DBI->connect("dbi:SQLite:./users.db", '', '', +{ Callbacks => { connected => sub { my $conn = shift; $conn->do(<<EOF); #テーブルの構造をココに書く CREATE TABLE user ( id INTEGER PRIMARY KEY, user_name varchar(10), sex varchar(10) default 'male', age INTEGER default 20, ); EOF return; }, }, sqlite_unicode => 1,#MySQLは、mysql_enable_utf8 => 1 , }); #Teng-0.14_05 package MyDB; use strict; use warnings; use utf8; use DBI; use Teng; use Teng::Schema::Loader; 永続化 our $TENG; sub teng { $TENG ||= do { my $dbh = DBI->connect("dbi:SQLite:./users.db", '', '', +{ Callbacks => { connected => sub { my $conn = shift; $conn->do(<<EOF); CREATE TABLE user ( id INTEGER PRIMARY KEY, user_name varchar(10), sex varchar(10) default 'male', age INTEGER default 20, ); EOF return; }, }, sqlite_unicode => 1, }); my $teng = Teng::Schema::Loader->load( dbh => $dbh, namespace => 'MyDB::Schema' ); Teng::Schema::Loader->load( dbh => $dbh, namespace => 'MyDB::Schema' ); } } } 1; 8 SELECT SQL文の書けるsearch_by_sqlメソッドを使う 複数行の取り出し 1行だけの取り出し use MyDB; use MyDB; my @users = MyDB->teng->search_by_sql( q{#SQL文が普通にかける SELECT id, user_name FROM user WHERE sex = ? AND age > ? }, ['male',20]#bind値は配列のリファレンスで設定 )->all; my $row = MyDB->teng->search_by_sql( q{ SELECT * FROM user WHERE user_name = ? }, ['hirobanex'] )->first; #Rowオブジェクトなるものがいる for my $row (@users) { #カラムはRowオブジェクトに #カラム名でメソッド呼び出し warn $row->id; warn $row->user_name; } 9 INSERT、UPDATE、DELETE SQL文の書けるdoメソッドを使う INSERT use MyDB; MyDB->teng->do(q{ INSERT INTO user ( user_name,sex,age ) VALUES ( ?,?,? ); },undef,('hirobanex','male','26')); # errorハンドリングはTengのほうで やってくれている UPDATE MyDB->teng->do(q{ UPDATE user SET user_name = ? ,age = ? WHERE user_name = ? },undef,('bane','27','hirobanex')); DELETE MyDB->teng->do(q{ DELETE user WHERE user_name = ? },undef,('bane')); 10 トランザクション 囲うだけ use MyDB; my $teng = MyDB->teng; my $txn = $teng->txn_scope; for my $user_name ('hiro','bane','ytnobody') { $teng->do(q{ INSERT INTO user (user_name) VALUES (?); },umdef,$user_name ); } $txn->commit; hachioji.pm 11 実際のO/Rマッパーの効用 Tengを使いこなしてやれることを広げるためのキーワード やれること Teng実装 トランザクションをシンプルに書ける DBIx::TransactionManager 突然コネクションが切られることはない $dbh->FETCH('Active'), $dbh->pingの確認 コンストラクション設定を楽にする × リファレンスとかでかっこ良く条件文を書く SQL::Maker インサートしたと同時にその中身とったり、 便利メソッドつくる Teng::Row(Rowオブジェクト)、 FindOrCreate, BulkInsertなど各種プラグイン SQL文を発行するタイミングでなんかする inflate,deflate(triggerはない) SELECTのIN構文になげるバインド値に 配列リファレンスを使いたい search_namedメソッド 12 その他Tengリファレンス cpanm Teng 0.14_05 http://perl-users.jp/articles/advent-calendar/2011/teng/ http://search.cpan.org/~nekokak/Teng-0.14_05/ http://walf443.github.com/teng-doc/ 最後はソースコードも読もう 13 最後に YAPC::Asia2012のトークに応募しました! 興味があったら、「いいね!」などお願いしますっ! 14
© Copyright 2024 Paperzz