Coat::Persistent at FPW2009

download Coat::Persistent at FPW2009

If you can't read please download the document

description

Coat::Persistent est un ORM écrit pour Perl en s'inspirant de l'API d'ActiveRecord de Rails. Cette présentation a été tenue aux journées Perl 2009

Transcript of Coat::Persistent at FPW2009

  • 1. Coat::Persistent Votre base de donnes portes d'objets FPW 2009 13 Juin 2009 Alexis Sukrieh http://www.sukria.net

2. Plan

  • Le concept ORM

3. Origines de Coat::Persistent 4. Mise en place de Coat::Persistent 5. Accder aux donnes (lecture/criture) 6. Relations entre tables / modles 7. Fonctionnement du cache 8. Le concept ORM Une mthode moderne etefficace pour manipuler les donnes 9. Le principe ORM

  • Un framework Objet

10. Une table devient une classe 11. Une ligne devient une instance 12. Une colonne devient un attribut 13. Le SQL est dsormais une couche de bas niveau 14. Avantages

  • Moins de code pour manipuler les donnes

15. Plus de code pour crire l'application 16. Factorisation du problme d'accs aux donnes 17. Facilits et puissance de l'approche Objet 18. Simplicit d'utilisation 19. Avantages

  • Moins de code pour manipuler les donnes

20. Plus de code pour crire l'application 21. Factorisation du problme d'accs aux donnes 22. Facilits et puissance de l'approche Objet 23. Simplicit d'utilisation 24. Moins de SQL 25. Avantages

  • Moins de code pour manipuler les donnes

26. Plus de code pour crire l'application 27. Factorisation du problme d'accs aux donnes 28. Facilits et puissance de l'approche Objet 29. Simplicit d'utilisation 30. Moins de SQL 31. Moins de SQL 32. Avantages Moins de SQL ??! 33. Avec du SQL ... my $sql='select * from table' ; my $sth=$dbh ->prepare( $sql ); $sth ->execute ordie $! ; while( my $row=$sth ->fetchrow_hashref()) { # ici on joue avec $row ... } On a donc 4 lignes pour pouvoir itrer sur des enregistrements... 34. CATS DON'T LIKE SQL 35. Avec Coat::Persistent foreach my $obj(Table->find()){ # ici on joue avec $obj ... } Je crois que le chat s'est calm... 36. Pourquoi vouloir moins de SQL ?

  • Pour les tches rptitives, SQL est lourd

37. Chaque fois qu'une requte SQL apparat dans du code, un risque d'injection est prsent 38. La validation des valeurs soumises en SQL est lourde 39. La prparation des valeurs l'est aussi (escaping, conversion de format) 40. Le temps pass manipuler SQL n'est pas consacr au code mtier 41. Mais le SQL est possible

  • On ne ferme pas pour autant la porte au SQL

42. Pour les requtes complexes, SQL reste un bon choix 43. Pour les requtes simples et courantes, il faut l'viter 44. Les ORM en Perl

  • Class::DBI

45. Les ORM en Perl

  • Class::DBI

46. DBIx::Class 47. Les ORM en Perl

  • Class::DBI

48. DBIx::Class 49. Rose::DB::Object 50. Les ORM en Perl

  • Class::DBI

51. DBIx::Class 52. Rose::DB::Object 53. ... 54. Pourquoi un nouvel ORM ? 55. Les origines de Coat::Persistent

  • ActiveRecord : l'ORM de Ruby on Rails

56. Coat : le mini Moose sans dpendances 57. Deux bonnes ides qui mritaient d'tre runies 58. Objectifs pour Coat::Persistent

  • Simple d'utilisation

59. Objectifs pour Coat::Persistent

  • Simple d'utilisation

60. Lger 61. Objectifs pour Coat::Persistent

  • Simple d'utilisation

62. Lger 63. Rapide 64. Objectifs pour Coat::Persistent

  • Simple d'utilisation

65. Lger 66. Rapide 67. Aussi prs que possible de l'API ActiveRecord 68. Objectifs pour Coat::Persistent

  • Simple d'utilisation

69. Lger 70. Rapide 71. Aussi prs que possible de l'API ActiveRecord 72. Interoprable (MySQL, SQLite, CSV, ...) 73. Mise en place Comment utiliser Coat::Persistentdans votre projet 74. Installation

  • cpan install Coat

75. cpan install Coat::Persistent 76. Le driver DBI pour votre SGBD 77. Une premier modle C::P package Camel ; useCoat; useCoat::Persistent; 78. Une premier modle C::Pavec MySQL package Camel ; useCoat; useCoat::Persistent; Coat::Persistent->map_to_dbi( mysql=>' dbname ',' dbuser ',' dbpass '); 79. Une premier modle C::Pavec SQLite package Camel ; useCoat; useCoat::Persistent; Coat::Persistent->map_to_dbi( sqlite=> ' dbname=dbfile '); 80. Une premier modle C::Pavec CSV package Camel ; useCoat; useCoat::Persistent; Coat::Persistent->map_to_dbi( csv=> ' f_dir=dbfile '); 81. Conventions

  • La mapping est possible par dfaut ou par classe

82. Le nom de la classe implique un nom de table 83. La clef primaire se nomme id 84. Une clef trangre se nomme table_id 85. On peut surcharger chacune de ces conventions 86. Surcharger les conventions package Camel ; useCoat; useCoat::Persistenttable_name=> ' camels ', primary_key=> ' cid '; Coat::Persistent->map_to_dbi( csv=> ' f_dir=dbfile '); 87. Terminer le mapping package Camel ; useCoat; useCoat::Persistent; has_p name => (isa => 'Str'); has_p age => (isa => 'Int'); sqlite> create table camel (id int, name varchar(25), age int); 88. Maintenant il est possible :

  • Remonter des objets partir de la base

89. Crer de nouvelles entres 90. Modifier des entres existantes 91. Accder au handle de la base de donnes 92. Obtenir des objets partir de requetes SQL complexes 93. Coat::Persistent est en place ! 94. Un modle Coat::Persistent

  • C'est une classe qui hrite de Coat::Object

95. C'est une classe qui hrite de Coat::Persistent 96. ce titre, elle bnficie de :

  • Mthodes statiques qui s'appliquent une table

97. Mthodes d'instances qui s'appliquent une ligne Pour chaque attribut dclar, des accesseurs et une srie de mthodes sont automatiquement dfinies : 98. Attribut et mthodes La dclaration de l'attribut foo implique :

    • $obj->foo()
  • 99. Class->find_by_foo()

100. Class->find_or_create_by_foo() 101. Class->find_or_initialize_by_foo() 102. Cration de donnes

  • Un nouvel objet Coat::Persistent n'est pas sauv en base tant que save() n'est pas appel

103. La mthode create() permet de faire un new() et un save() 104. Des mthodes permettent de faire des crations d'objet avec ou sans sauvegarde selon l'existence d'un enregistrement particulier 105. Cration de donnes

  • Class->new() : cre une instance en mmoire

106. $obj->save() : sauve l'instance dans la base de donne 107. Class->create() : cre et sauve l'instance 108. Class->find_or_create_by_ATTR(val) : find_by_ATTR(val) ou create(ATTR => val) 109. Class->find_or_initialize_by_ATTR(val) : find_by_ATTR(val) ou new(ATTR => val) 110. Exemple de cration Perl> my $joe = Camel->new(name =>'joe',age => 7); $Camel1 = Camel=HASH(0x8dcf7a0); Perl> $joe->save 1 sqlite> select * from camel where id = 1; 1|joe|7 111. Exemple de cration (plus court) Perl> my $joe = Camel->create(name =>'night',age => 4); $Camel1 = Camel=HASH(0x8dcf7a0); sqlite> select * from camel where id = 1; 1|joe|7 2|night|4 112. Lecture

  • Pour lire les donnes existantes, on utilise un finder

113. Le contexte d'appel est important (on remonte N entres avec un contexte de liste et uniquement la premire en contexte scalaire) 114. Les finders peuvent se dcliner 115. find, find_by_attribut, find(id), find('condition') ... 116. find en contexte de liste Perl> my @camels = Camel->find(); $ARRAY1 = [ Camel=HASH(0x9cfc568), Camel=HASH(0x9cfc718), Camel=HASH(0x9cfc7c8) ]; 117. find avec un id Perl> my $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc568) 118. find avec plusieurs id Perl> my @camels = Camel->find(1,2); $ARRAY1 = [ Camel=HASH(0x9ba0648), Camel=HASH(0x9cfc818) ]; 119. find avec un attribut Perl> my $joe = Camel->find_by_name('joe'); $Camel1 = Camel=HASH(0x9cfc568) Perl> $joe->name; 'joe' 120. find avec une condition Perl> @camels = Camel->find('age > 10'); $Camel1 = Camel=HASH(0x9d0af78); Perl> $camels[0]->age 12 121. find avec des options Perl> my @camels = Camel->find('age > 3',{ order => 'name', limit => '5', }); 122. find avec du SQL Perl> @camels = Camel->find_by_sql('select * from camel where age is not null'); $ARRAY1 = [ Camel=HASH(0x9cfc528), Camel=HASH(0x9cfca78), Camel=HASH(0x94c3380) ]; 123. Modifier Perl> $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc528) Perl> $camel->age(3); 3 Perl> $camel->save; 1 124. Supprimer Perl> $camel = Camel->find(1); $Camel1 = Camel=HASH(0x9cfc528) Perl> $camel->delete; 1 Perl> $camel = Camel->find(1); undef 125. N'oublions pas Coat

  • Le hooks de Coat (Moose) s'appliquent trs bien ici

126. Chaque mthode propose par C::P est interceptable via les hooks Coat before, after et around 127. Les mthodes BUILD et DEMOLISH sont implmentables par les objets C::P 128. Types utilisateur et coercition 129. Les hooks

  • before save => sub { ... }

130. after save => sub { } 131. sub BUILD { ... } 132. sub DEMOLISH { ... } 133. ... 134. Types et Coercition subtype 'DateTime'=> as 'Str' => where { /d{4}-dd-dd dd:dd:dd/ }; coerce 'DateTime' => from 'Int' => via {convert_time_to_datetime_str($_) }; 135. Types et Coercition has_p 'created_at' => ( is => 'rw', isa => 'DateTime', coerce => 1, ); before 'save' => sub { my ($self) = @_; $self->created_at(time()); }; 136. Les relations entre tables 137. Relations ct SQL ... sqlite> create table master (id int, name varchar(25)); sqlite> alter table camel add column master_id int; 138. et ct Perl package Camel ; useCoat; useCoat::Persistent; has_p name => (isa =>'Str' ); has_p age => (isa =>'Int' ); has_one'master'; ; 139. et ct Perl package Master ; useCoat; useCoat::Persistent; has_p name => (isa =>'Str' ); has_many'camels', class_name => 'Camel'; ; 140. Le matre des chameaux Perl> my $m = Master->create(name => 'Al Kabir') $Master1 = Master=HASH(0x913c168); Perl> my @camels => Camel->find(); $ARRAY1 = [ Camel=HASH(0x913c5e8), Camel=HASH(0x913c588) ]; Perl> map { $_->master($m); $_->save;} @camels; 141. Trouver le matre Perl> my $camel = Camel->find(1); $Camel1 = Camel=HASH(0xa07cd60); Perl> $camel->master $Master1 = Master=HASH(0xa07d050); Perl> $camel->master->name Al Kabir 142. Trouver les chameaux Perl> my $master = Master->find(1); $Master1 = Master=HASH(0xa07d050); Perl> my @camels = $master->camels; $ARRAY1 = [ Camel=HASH(0xa07ce00), Camel=HASH(0xa07d080) ]; 143. Accler les choses

  • Pour amliorer les performances, on peut cacher les rsultats des requtes SQL

144. Le cache est activable la demande, par Classe ou pour l'ensemble du processus 145. Pour chaque requte SQL gnre (pour un set de valeurs donnes) C::P maintient une entre en cache avec le rsultat 146. Ce rsultat en cache est retourn s'il existe 147. Accler les choses

  • L'expiration des donnes est gre en interne par Cache::FastMmap

148. On peut activer/dsactiver le cache la vole 149. Exemple de Cache Pour l'ensemble du processus (toutes les classes C::P sont affectes) Coat::Persistent ->enable_cache( expire_time=>'1h' , cache_size =>'50m' , share_file =>'/var/cache/myapp.cache' , ); 150. Exemple de Cache Uniquement pour la classe utilise Camel ->enable_cache( expire_time=>'1h' , cache_size =>'50m' , share_file =>'/var/cache/myapp.cache' , ); 151. Pour la suite ...

  • Gestion de l'option join dans les finder

152. Migrations (classe Coat::Persistent::Migration) 153. Valider de nouveaux drivers DBI 154. Mthodes manquantes de ActiveRecord 155. Optimisations (occupation mmoire, requtes gnres) 156. Pour Contribuer

  • Les patchs sont toujours bienvenus

157. svn co svn://svn.sukria.net:2015/Coat-Persistent 158. Bugs : http://rt.cpan.org 159. Pour me contacter : [email protected]