31
DBIx::Class Работаем с базой в стиле Perl

DBIx Class

  • Upload
    i-

  • View
    2.615

  • Download
    2

Embed Size (px)

Citation preview

Page 1: DBIx Class

DBIx::Class

Работаем с базой в стиле Perl

Page 2: DBIx Class

Зачем нужен ORM?

ORM = Объектно-реляционная проекцияДля сохранения объектов в базу, мы их должны преобразовать в реляционную форму и наоборотВ нашем коде получается смесь двух совершенно разных языков - SQL и Perl.Это тупо неудобно!my $message = $user->messages->find( $message_id );

Page 3: DBIx Class

DBIx::Class

Почему именно он?Самый популярныйБольшое количество плагиновЕсть связки с Catalyst и HTML::FormFuЯ це люблю™

Page 4: DBIx Class

Импорт структуры базы

perl \-MDBIx::Class::Schema::Loader=dump_to_dir:/foo/bar \-MMy::Schema \-e 'My::Schema->connection("dbi:Pg:...", ...)'

Page 5: DBIx Class

Основы основ

В DBIx::Class есть две основные сущностиResultSetRow

ResultSet - это структура для формирования запроса. Если метод возвращает этот тип данных, то  он не полезет в базу!

Row - полученная из базы строка. К её столбцам можно обратиться как $row->column_name

Page 6: DBIx Class

Расширение 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;

Page 7: DBIx Class

Расширение 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;

Page 8: DBIx Class

Начинаем работать

Получаем 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' } )

Page 9: DBIx Class

Начинаем работать (строки)

my @rows = $rs->all;$row->id$row->name$row->name( 'Изя' )$row->update$row->delete$row->insert

Page 10: DBIx Class

Отношения

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' } );

Page 11: DBIx Class

Апдэйты

Строки $row->name( $value );$row->update;$row = $rs->new({});$row->name( $value );$row->insert;$row->delete;

 ResultSets$rs->update( { is_unread => 0 } );$rs->delete; #!!!! не про****те

Page 12: DBIx Class

Вкусняшки

Page 13: DBIx Class

Prefetch

Нам нужно сэкономить на запросах

my $posts = $schema->resultset('Posts');foreach my $row ($posts->all) {    say $post->forum->moderator->name; }

Page 14: DBIx Class

Всего один запрос

my $posts = $schema->resultset('Posts')->search(undef,{     prefetch => {        forum => 'moderator'     }}); foreach my $post ( $posts->all ) {    say $post->forum->moderator->name; }

Page 15: DBIx Class

Подзапросы

my $rs = $people->young->sexy->girls;$phone_db->search( { user_id => {     -in => $rs->as_query} } );

Page 16: DBIx Class

Paging

Самая частая задача!Зачем её делать дважды?$resultset->search( { rows => 50 } );$resultset->page(2); $resultset->pager (Data::Page);

Page 17: DBIx Class

Аггрегативные функции

$posts->get_column('rating')->max; $users->count; $users->get_column('age')->avg;

Page 18: DBIx Class

Inflate, Deflate

Мы получаем тип данных из базы и превращаем его в красивый объект.И наоборот

 Например, мы можем прозрачно сохранять перловую структуру в каком-то поле!!man DBIx::Class::InflateColumn

Page 19: DBIx Class

Выходим из резервации

плагины

Page 20: DBIx Class

DBIx::Class::FrozenColumns

Прозрачно сохраняем дополнительные столбцы в одном поле$user->name; #этот столбец у нас лежит в базе$user->has_some_useless_property; # а этого - нет

Page 21: DBIx Class

DBIx::Class::DynamicSubclass

В зависимости от какого-то флагового поля в базе, может создавать объекты других типов.Получаем записи из таблицы Animals, а они сразу bless-ятся в кошечек и собачек.

Page 22: DBIx Class

DBIx::Class::CustomPrefetch*

Упрощение работы с несколькими СУБД. Аналог prefetch, но между базами            * Данная информация опубликована на правах рекламы :-)

Page 23: DBIx Class

Отладка и оптимизация

Page 24: DBIx Class

ORM - гавно

( как сказал один дядька с Highload )

Итак,

Page 25: DBIx Class

Убедитесь, что дело в базе

DBI_PROFILE=1 ./my_script.plDBI::Profile: 0.046747s 2.34% (39 calls) comments_test.pl @ 2009-10-16 02:41:41

Page 26: DBIx Class

Если таки в базе

DBIС_TRACE=1 ./my_script.pl DBI_PROFILE=2 ./my_script.pl

Page 27: DBIx Class

Найдите медленные запросы

man DBIx::Class::QueryLog

Page 28: DBIx Class

Тормоза в DBIx::Class

Красная пилюля.Применять по крайней необходимости!

$rs->result_class('DBIx::Class::ResultClass::HashRefInflator');

Page 29: DBIx Class

Масштабирование

= репликация

Page 30: DBIx Class

Включаем репликацию

$schema->storage_type( [ '::DBI::Replicated', {balancer=>'::Random'} ] ); $schema->storage->connect_replicants(

[$dsn1, $user, $pass, \%opts], [$dsn2, $user, $pass, \%opts],[$dsn3, $user, $pass, \%opts],);

Page 31: DBIx Class

Profit!