dbix class
Post on 20-May-2015
2.616 Views
Preview:
TRANSCRIPT
DBIx::Class
Работаем с базой в стиле Perl
Зачем нужен ORM?
ORM = Объектно-реляционная проекцияДля сохранения объектов в базу, мы их должны преобразовать в реляционную форму и наоборотВ нашем коде получается смесь двух совершенно разных языков - SQL и Perl.Это тупо неудобно!my $message = $user->messages->find( $message_id );
DBIx::Class
Почему именно он?Самый популярныйБольшое количество плагиновЕсть связки с Catalyst и HTML::FormFuЯ це люблю™
Импорт структуры базы
perl \-MDBIx::Class::Schema::Loader=dump_to_dir:/foo/bar \-MMy::Schema \-e 'My::Schema->connection("dbi:Pg:...", ...)'
Основы основ
В DBIx::Class есть две основные сущностиResultSetRow
ResultSet - это структура для формирования запроса. Если метод возвращает этот тип данных, то он не полезет в базу!
Row - полученная из базы строка. К её столбцам можно обратиться как $row->column_name
Расширение Row-объектов
package My::Schema::Users;__PACKAGE__->table( 'users' );__PACKAGE__->add_columns(qw(id first last patronymic));
sub initials { my $self = shift; return join ' ', $self->last, map { substr($_,0,1) . "."} ( $self->first, $self->patronymic);}
1;
say $user->first;say $user->last;say $user->fio;
Расширение ResultSet-объектов
package My::Schema::People;__PACKAGE__->resultset_class( 'My::ResultSet::People' );1;package My::ResultSet::People;sub young { my $self = shift; $self->search( { age => { -between => [ 17, 20 ] } } );} my @girls = $schema->resultset('People')->young->sexy->girls;
Начинаем работать
Получаем ResultSet:my $rs = $schema->resultset('Название');
$rs->search( query, params ) $rs->slice(first, last)и их комбинации:$rs->search( { sex => 'f' } )->search( { age => 18 } )->slice(0,1)->first;$rs->find( $id1, $id2, $id3 )$rs->allwhile ( my $row = $rs->next ) {}$rs->count; $rs->new( { name => 'Petya' } )
Начинаем работать (строки)
my @rows = $rs->all;$row->id$row->name$row->name( 'Изя' )$row->update$row->delete$row->insert
Отношения
package My::Schema::User;__PACKAGE__->add_columns( qw(id name gender) ); __PACKAGE__->has_many( 'posts' => 'My::Schema::Posts', 'user_id' );__PACKAGE__->belongs_to( gender => 'My::Schema::Genders' );1; ...say $user->gender->name; #male say $user->posts->first->title; # Как размножаются ёжики?$user->add_to_posts( { title => 'RE: Как размножаются ёжики' } );$user->posts->find( $post_id );$user->search_related('posts')->search_related('comments', { order_by => 'date' } );
Апдэйты
Строки $row->name( $value );$row->update;$row = $rs->new({});$row->name( $value );$row->insert;$row->delete;
ResultSets$rs->update( { is_unread => 0 } );$rs->delete; #!!!! не про****те
Вкусняшки
Prefetch
Нам нужно сэкономить на запросах
my $posts = $schema->resultset('Posts');foreach my $row ($posts->all) { say $post->forum->moderator->name; }
Всего один запрос
my $posts = $schema->resultset('Posts')->search(undef,{ prefetch => { forum => 'moderator' }}); foreach my $post ( $posts->all ) { say $post->forum->moderator->name; }
Подзапросы
my $rs = $people->young->sexy->girls;$phone_db->search( { user_id => { -in => $rs->as_query} } );
Paging
Самая частая задача!Зачем её делать дважды?$resultset->search( { rows => 50 } );$resultset->page(2); $resultset->pager (Data::Page);
Аггрегативные функции
$posts->get_column('rating')->max; $users->count; $users->get_column('age')->avg;
Inflate, Deflate
Мы получаем тип данных из базы и превращаем его в красивый объект.И наоборот
Например, мы можем прозрачно сохранять перловую структуру в каком-то поле!!man DBIx::Class::InflateColumn
Выходим из резервации
плагины
DBIx::Class::FrozenColumns
Прозрачно сохраняем дополнительные столбцы в одном поле$user->name; #этот столбец у нас лежит в базе$user->has_some_useless_property; # а этого - нет
DBIx::Class::DynamicSubclass
В зависимости от какого-то флагового поля в базе, может создавать объекты других типов.Получаем записи из таблицы Animals, а они сразу bless-ятся в кошечек и собачек.
DBIx::Class::CustomPrefetch*
Упрощение работы с несколькими СУБД. Аналог prefetch, но между базами * Данная информация опубликована на правах рекламы :-)
Отладка и оптимизация
ORM - гавно
( как сказал один дядька с Highload )
Итак,
Убедитесь, что дело в базе
DBI_PROFILE=1 ./my_script.plDBI::Profile: 0.046747s 2.34% (39 calls) comments_test.pl @ 2009-10-16 02:41:41
Если таки в базе
DBIС_TRACE=1 ./my_script.pl DBI_PROFILE=2 ./my_script.pl
Найдите медленные запросы
man DBIx::Class::QueryLog
Тормоза в DBIx::Class
Красная пилюля.Применять по крайней необходимости!
$rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
Масштабирование
= репликация
Включаем репликацию
$schema->storage_type( [ '::DBI::Replicated', {balancer=>'::Random'} ] ); $schema->storage->connect_replicants(
[$dsn1, $user, $pass, \%opts], [$dsn2, $user, $pass, \%opts],[$dsn3, $user, $pass, \%opts],);
Profit!
top related