DBICはみんな使ってるだろうから省略
package Proj::Driver;
use Data::ObjectDriver::Driver::DBI;
sub driver {
Data::ObjectDriver::Driver::DBI->new(
dsn => 'dbi:mysql:proj',
username => 'proj',
password => 'passwd',
)
}
package Proj::Data::Todo;
use base 'Data::ObjectDriver::BaseObject';
use Proj::Driver;
__PACKAGE__->install_properties({
columns => [qw/id body delete_fg done_at created_on updated_on/],
datasource => 'todo',
primary_key => 'id',
driver => Proj::Driver->driver,
});
#! perl
use Proj::Data::Todo;
my $todo = Proj::Data::Todo->new;
$todo->body('learn DOD!');
$todo->save; # insert!
say $todo->body; # 'learn DOD!'
$todo->done_at(DateTime->now);
$todo->save # update!
package Proj::Data::Tag;
use base 'Data::ObjectDriver::BaseObject';
use Proj::Driver;
__PACKAGE__->install_properties({
columns => [qw/id name created_on updated_on/],
datasource => 'tag',
primary_key => 'id',
driver => Proj::Driver->driver,
});
package Proj::Data::TodoTag;
use base 'Data::ObjectDriver::BaseObject';
use Proj::Driver;
__PACKAGE__->install_properties({
columns => [qw/id todo_id tag_id created_on updated_on/],
datasource => 'todo_tag',
primary_key => 'id',
driver => Proj::Driver->driver,
});
ここまでは一緒
package Proj::Data::TodoTag;
#..nop
__PACKAGE__->has_a({
class => 'Proj::Data::Todo',
column => 'todo_id',
method => 'todo',
parent_method => 'tags',
});
__PACKAGE__->has_a({
class => 'Proj::Data::Tag',
column => 'tag_id',
method => 'tag',
parent_method => 'todos',
});
#! perl
## primary key select
my $todo = Proj::Data::Todo->lookup(1);
## Todoに設定されているTagの取得
my @tags = map { $_->tag->name } $todo->tags;
#! perl
my $rs = Proj::Data::Todo->result(
{},
{
sort => 'id',
direction => 'descend',
}
);
$rs->add_constraint({done_on => \'IS NOT NULL'});
while ( not $rs->is_finished ) {
my $todo = $rs->next;
}
continued...
#! perl
my $rs = Proj::Data::Todo->result(
{},
{
sort => 'id',
direction => 'descend',
}
);
$rs->add_constraint({done_on => \'IS NOT NULL'});
while ( not $rs->is_finished ) {
my $todo = $rs->next;
}
add_constraintを呼び出してインクリメンタルに検索条件追加できる
package Proj::Driver;
use Data::ObjectDriver::Driver::DBI;
use Data::ObjectDriver::Driver::Cache::Memcached; ## 追加
use Cache::Memcached; ## 追加
sub driver {
Data::ObjectDriver::Driver::Cache::Memcached->new(
## Cacheの設定
cache => Cache::Memcached->new({servers => ['127.0.0.1:11211']}),
## CacheにHitしなかった場合のDB接続設定
fallback => Data::ObjectDriver::Driver::DBI->new(
dsn => 'dbi:mysql:proj',
username => 'proj',
password => 'passwd',
),
);
}
Data::ObjectDriver::Driver::DBIの上に Data::ObjectDriver::Driver::Cache::Memcached がかぶさっただけ。 これだけで、自動的にキャッシュしてくれます。
package Pro::Driver;
use Cache::Memcached;
use Data::ObjectDriver::Driver::Cache::Memcached;
use Data::ObjectDriver::Driver::Partition;
use Data::ObjectDriver::Driver::DBI;
sub driver {
Data::ObjectDriver::Driver::Cache::Memcached->new(
cache => Cache::Memcached->new({servers => ['127.0.0.1:11211']}),
fallback => Data::ObjectDriver::Driver::Partition->new(
get_driver => \&get_driver,
),
),
};
package Proj::Driver;
# ...nop
sub get_driver {
my($terms) = @_;
## some partitionning rule
Data::ObjectDriver::Driver::DBI->new(
dsn => 'dbi:SQLite:./dat/todo_' . $rule .'.dat',
pk_generator => \&generate_pk,
);
}
use Data::YUID::Generator;
sub generate_pk {
my $obj = shift;
$obj->id(Data::YUID::Generator->new->get_id);
}
package Proj::Schema;
use Fey::ORM::Schema;
use Fey::DBIManager::Source;
use Fey::Loader;
my $source = Fey::DBIManager::Source->new(
dsn => 'dbi:mysql:diary',
username => 'diary',
password => 'passwd'
);
my $schema = Fey::Loader->new( dbh => $source->dbh() )->make_schema();
has_schema $schema;
__PACKAGE__->DBIManager()->add_source($source);
package Proj::Schema::Diary;
use Proj::Schema;
use Fey::ORM::Table;
my $schema = Proj::Schema->new();
has_table( $schema->Schema()->table('diary') );
#! perl
my $diary = Proj::Schema::Diary->insert(
body => 'nice day!',
created_on => DateTime->now
);
say $diary->body; # nice day!
package Proj::Schema::Tag;
use Proj::Schema;
use Fey::ORM::Table;
my $schema = Proj::Schema->new();
has_table( $schema->Schema()->table('tag') );
package Proj::Schema::DiaryTag;
use Proj::Schema;
use Fey::ORM::Table;
my $schema = Proj::Schema->new();
has_table $schema->Schema()->table('diary_tag');
package Proj::Schema::Diary;
has_many diary_tags => (
table => $schema->Schema()->table('diary_tag')
);
package Proj::Schema::DiaryTag;
has_one $schema->Schema()->table('diary');
my $diary = Proj::Schema::Diary->new(id => 1);
say $diary->id; # 1
say $diary->body; # nice day!
my $diary_tags = $diary->diary_tags;
while (my $row = $diary_tags->next) {
say $row->tag->name; # perl, life, some more tags...
}
package Proj::Schema::Diary;
use Fey::Object::Iterator;
sub perl_entries {
my $class = shift;
my $schema = $class->SchemaClass()->Schema();
my $select = $class->SchemaClass()->SQLFactoryClass()->new_select();
my ( $diary_t, $diary_tag_t, $tag_t ) =
$schema->tables( 'diary', 'diary_tag', 'tag' );
$select->select( $diary_t )
->from( $diary_t )->from( $diary_tag_t )->from( $tag_t )
->where(
$diary_t->column('id'), '=', $diary_tag_t->column('diary_id')
)->and(
$diary_tag_t->column('tag_id'), '=', $tag_t->column('id')
)->and(
$tag_t->column('name'), '=', 'perl'
);
my $dbh = $class->_dbh($select);
my $sth = $dbh->prepare( $select->sql($dbh) );
return Fey::Object::Iterator->new(
classes => [
$class->meta()->ClassForTable(
$diary_t, $diary_tag_t, $tag_t
)
],
handle => $sth,
bind_params => [ $select->bind_params() ],
);
}
my $it = Prj::Schema::Diary->perl_entries;
while (my $row = $it->next) {
say $row->body;
}
複雑なSQLを生成してイテレータオブジェクトにして利用可能
ご清聴有り難うございました