Perl Hackers Hub

第30回 データベースプログラミング入門―汎用インタフェースDBIと,O/RマッパTengの使い方(3)

この記事を読むのに必要な時間:およそ 4 分

(1)こちら⁠2)こちらから。

Tengの使い方

(2)ではDBIを使ってどのようにデータベースを操作できるかを解説しました。DBIはそのままでも十分に高機能ですが,ハッシュリファレンスや配列リファレンスで表現された単一行のデータをそのまま利用して複雑なロジックを実装すると,コードが複雑になってしまう場合があります。ロジックが複雑化するケースは単一行のデータをクラスに紐づけてオブジェクト化すると扱いやすくなることがよくあります。

O/RマッパObject-Relational Mapperは,その名のとおり単一行のデータをクラスに紐づけてオブジェクト化することを主目的とした実装です。O/Rマッパを利用することで,データベースを扱う処理をよりシンプルに実装できます。多くのO/Rマッパは,O/Rマッピングのほかにもクエリビルダなどのアプリケーション開発に便利な機能を備えています。

(3)では,Perl製のO/Rマッパの一つであるTengの機能とその基本的な使い方を解説します。なお,本稿のコードは,執筆時点の最新であるTengのバージョン0.25を前提に記述しています。

Tengとは何か

Tengは非常にシンプルなO/R マッパです。DBIx::ClassなどのほかのO/Rマッパと比較して,シンプルで覚えやすく,トラブル時にコードが追いやすいという特徴を持ちます。また,余計な機能がないため,O/Rマッパの学習にも適しています。

Tengのインストール

cpanmでインストールします。

$ cpanm Teng

モジュールがロードできればインストールに成功しています。

$ perl -MTeng -E 'say $Teng::VERSION'

基本的な使い方

本項では,Tengを使ってデータベースプログラミングを行う基本的な手順を解説します。

Tengを継承したクラスの用意

Tengを利用するためには,Tengを継承したクラスを用意する必要があります。今回はMyApp::DBに用意します。次のようにただ継承するだけです。

package MyApp::DB;
use parent qw/Teng/;
1;
スキーマ情報の定義

スキーマ情報とは,データベース構造の情報のことです。具体的には,どのようなテーブルがあり,どのようなカラムが存在し,どのような制約がかかっているのかなど,どのような構造のデータが挿入できるかがわかる情報を指すと思ってください。

O/Rマッパは,O/Rマッパがスキーマ情報を知っていることを前提にデータベースプログラミングをサポートしてくれます。Tengも例外ではなく,TengではTeng::Schema::LoaderTeng::Schema::Declareの2つの方法でスキーマ情報を得ることができます。

Teng::Schema::Loaderを利用すると,Tengはデータベースサーバから自動的にスキーマ情報を取得して利用します。細かいスキーマ情報の指定はできませんが,その代わり手軽に利用できるのが特徴です。短期的に運用する小規模なサービスを作るときやちょっと試してみるときなどに便利です。

Teng::Schema::Declareを利用すると,内部DSLDomain Specific Languageドメイン特化言語)で任意のスキーマ情報をクラスとして定義できます。今回は解説しないinflate/deflate機能注6の利用や,データサイズの大きなカラムをあえてTengのスキーマ定義から削るなど,細かいスキーマ情報の指定も行えます。

また,Teng::Schema::Dumperを利用すると,データベースサーバからスキーマ情報を取得し,Teng::Schema::Declareを利用したスキーマクラスのソースコードを生成できます。基本的にはTeng::Schema::Dumperを利用してスキーマクラスを生成するとよいでしょう。

今回はTeng::Schema::Loaderを利用してみましょう。次のようにして利用できます。

use DBI;
use MyApp::DB;
use Teng::Schema::Loader;

my $dbh = DBI->connect(...);
my $teng = Teng::Schema::Loader->load(
    dbh => $dbh,
    namespace => 'MyApp::DB'
);
注6)
データベースのデータとPerlのデータ構造を相互変換する処理を定義することにより,自動変換を行ってくれる機能です。
データベースへの接続――connect_info

Teng::Schema::Loaderを利用する場合,事前にデータベースへの接続を行う必要があるため,スキーマ情報を取得するために利用したデータベースハンドラが再利用されます。そのため,DBIで一度接続してしまえば接続のためにそれ以上の処理は必要ありません。

Teng::Schema::Declareを利用する場合は次のようにして接続できます。

use MyApp::DB;
use MyApp::DB::Schema;

my $teng = MyApp::DB->new({
    connect_info => [$dsn, $user, $pass, $attr],
    schema_class => 'MyApp::DB::Schema',
});

connect_infoDBIconnectメソッドに渡すべき値を渡すことにより,接続先のデータベースを指定します。schema_classにはTeng::Schema::Declareで定義したスキーマクラスを指定します。

DBIのデータベースハンドラの取得――dbh

Tengにはトランザクションの状態管理も考慮した,暗黙的な再接続機能が実装されています注7)⁠dbhメソッドにより,常に接続が確立されているデータベースハンドラを得ることができます。高速化のためにDBIのメソッドを直接利用したい場合などはdbhメソッドを利用するとよいでしょう。

$teng->dbh->prepare(...);
注7)
トランザクションの途中で再接続が行われようとした場合はdieするようになっています。
単一行の取得――single

単一の行を取得したい場合はsingleメソッドを利用します。Tengはクエリビルダとして標準でSQL::Makerを利用しているので,SQL::Makerのフォーマットで指定を行います。詳しくはSQL::Makerのドキュメントを参照してください。

my $row = $teng->single(chat => {
    # WHERE
    room => 'room1',
    user => 'karupanerura',
}, {
    # ORDER BY,LIMIT
    order_by => { created_at => 'DESC' },
    limit => 1,
});

# Row オブジェクトからカラムの値が得られる
say $row->room;

なお,singleメソッドでは暗黙的にLIMITが1であるものとしてSQLが生成されますが,可読性のために基本的にはLIMITを明示したほうがよいでしょう。

著者プロフィール

佐藤健太(さとうけんた)

1990年,千葉県生まれ。2011年に株式会社モバイルファクトリーに入社。

現在はソーシャルアプリ事業部所属のリードエンジニアとして,主にPerlによるWebアプリの設計と開発に従事。

Androidアプリの開発,ミドルウェアの検証と導入,パフォーマンスチューニング等も行う。セキュリティ,データベース,ソフトウェアアーキテクチャに関心が高い。

2014年5月にGotanda.pmを発足。YAPC::Asia等でもスピーカーをするなど,Perl関連のコミュニティに積極的に参加している。

好きな言語はPerlとLisp。最近はXSを勉強中。日本酒と寿司とロックンロールが好物。

URL:http://karupas.org/

コメント

コメントの記入