ビギナーだから使いたいo/rマッパー ~tengを使った開発~

15
ビギナーだから使いたいO/Rマッパー Tengを使った開発~ Hirobanex(Akabane Hiroyuki) 2012-06-29@Perl Beginners #3

Upload: akabane-hiroyuki

Post on 26-May-2015

3.467 views

Category:

Technology


2 download

DESCRIPTION

Perl Beginners#3で発表したSQL/DB初心者向けのPerlのO/RマッパーTengの使い方のチュートリアルです。

TRANSCRIPT

Page 1: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

Hirobanex(Akabane Hiroyuki)

2012-06-29@Perl Beginners #3

Page 2: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

1

コンテンツ

• Tengを使いたい3つの理由 • ビギナーにオススメのTengの導入方法 • 本来のO/Rマッパーの効用

Page 3: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

2

Tengを使いたい3つの理由

• DBIはよくわからん • O/Rマッパーだと開発が抜群に早くなる • コード量が少ないし、勉強になる

Page 4: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

3

生DBIはよくわからん

• コンストラクション時の設定って? • セレクト系メソッドどれ使えばいい? • ドキュメントが長すぎてどこ読めば? • トランザクションって? • 突然、コネクション切れる?

Page 5: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

4

セレクト系メソッドどれ使えばいい?

•fetchrow_arrayref •fetchrow_array •fetchrow_hashref •fetchall_arrayref •fetchall_hashref

•selectrow_array •selectrow_arrayref •selectrow_hashref •selectall_arrayref •selectall_hashref •selectcol_arrayref

refとかarrayとかhashとか、頭がパンクします・・・

Page 6: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

5

O/Rマッパーだと開発が抜群に早くなる

use DBI; my @data_set = ( [26,'hiro'], [27,'bane'], ); my $dbh = DBI->connect("DBI:mysql:db_name;", "root", "pass",{ AutoCommit => 0, }); for my $data (@data_set) { my ($age,$name) = @$data; 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); #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');

#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",); my $teng = Teng::Schema::Loader->load( dbh => $dbh, namespace => 'MyAPP::DB', ); $teng->load_plugin('FindOrCreate'); my $txn = $teng->txn_scope; for my $data (@data_set) { my ($age,$name) = @$data; my $row = $teng->find_or_create('age',{ age => $age }); $teng->insert('user', { age_id => $row->id, name => $name }); } $txn->commit;

DBI Teng

複数データ群をリレーションつけて登録する場合のコード比較

20行 7行

Page 7: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

6

コード量が少ないし、勉強になる

• オーサーは日本人のnekokakさん • 不明点は誰かに聞けばわかりそう • 日本語情報豊富 • 挙動確認がコード量が少ないため楽 • コードをおうと、Perlの勉強になる

Page 8: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

7

ビギナーにオススメのTengの導入方法

• Tengのnew(オブジェクトの作り方) • SELECT • INSERT、UPDATE、DELETE • トランザクション

DBIもよくわからんけど、とにかく早く使ってみたい人向け

Page 9: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

#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, }); Teng::Schema::Loader->load( dbh => $dbh, namespace => 'MyDB::Schema' ); } } 1; 8

Tengのnew(オブジェクトの作り方)

#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 , }); my $teng = Teng::Schema::Loader->load( dbh => $dbh, namespace => 'MyDB::Schema' ); }

Teng::Schema::Loaderというのを使うと楽

とりあえずメソッド化 永続化

Page 10: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

9

SELECT

SQL文の書けるsearch_by_sqlメソッドを使う

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; #Rowオブジェクトなるものがいる for my $row (@users) { #カラムはRowオブジェクトに #カラム名でメソッド呼び出し warn $row->id; warn $row->user_name; }

use MyDB; my $row = MyDB->teng->search_by_sql( q{ SELECT * FROM user WHERE user_name = ? }, ['hirobanex'] )->first;

1行だけの取り出し 複数行の取り出し

Page 11: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

10

INSERT、UPDATE、DELETE

SQL文の書けるdoメソッドを使う

use MyDB; MyDB->teng->do(q{ INSERT INTO user ( user_name,sex,age ) VALUES ( ?,?,? ); },undef,('hirobanex','male','26')); # errorハンドリングはTengのほうでやってくれている

INSERT MyDB->teng->do(q{ UPDATE user SET user_name = ? ,age = ? WHERE user_name = ? },undef,('bane','27','hirobanex'));

UPDATE

MyDB->teng->do(q{ DELETE user WHERE user_name = ? },undef,('bane'));

DELETE

Page 12: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

hachioji.pm 11

トランザクション

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;

囲うだけ

Page 13: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

12

実際のO/Rマッパーの効用

やれること Teng実装

トランザクションをシンプルに書ける DBIx::TransactionManager

突然コネクションが切られることはない $dbh->FETCH('Active'), $dbh->pingの確認

コンストラクション設定を楽にする ×

リファレンスとかでかっこ良く条件文を書く SQL::Maker

インサートしたと同時にその中身とったり、 便利メソッドつくる

Teng::Row(Rowオブジェクト)、 FindOrCreate, BulkInsertなど各種プラグイン

SQL文を発行するタイミングでなんかする inflate,deflate(triggerはない)

SELECTのIN構文になげるバインド値に 配列リファレンスを使いたい

search_namedメソッド

Tengを使いこなしてやれることを広げるためのキーワード

Page 15: ビギナーだから使いたいO/Rマッパー ~Tengを使った開発~

14

最後に

YAPC::Asia2012のトークに応募しました!

興味があったら、「いいね!」などお願いしますっ!