Loading...
Flash Player 9 (or above) is needed to view slideshows. We have detected that you do not have it on your computer.To install it, go here
Slideshow Transcript
- Slide 1: Demystifying DBIx::Class Jay Shirley <jshirley@coldhardcode.com> http://our.coldhardcode.com/svn/DBIC-Beer
- Slide 2: Mystic?
- Slide 3: Why are ORMs scary?
- Slide 4: Why are ORMs scary? • Enterprise-y
- Slide 5: Why are ORMs scary? • Enterprise-y • Loss of control
- Slide 6: Why are ORMs scary? • Enterprise-y • Loss of control • History (Class::DBI)
- Slide 7: Why are ORMs scary? • Enterprise-y • Loss of control • History (Class::DBI) • (A triumph of multiple inheritance)
- Slide 8: Retort.
- Slide 9: Enterprise-y
- Slide 10: Enterprise-y • Enterprise = Java
- Slide 11: Enterprise-y • Enterprise = Java • DBIx::Class is written in perl
- Slide 12: Loss of Control
- Slide 13: Loss of Control • Still programmatic
- Slide 14: Loss of Control • Still programmatic • Use SQL::Abstract rather than SQL
- Slide 15: Loss of Control • Still programmatic • Use SQL::Abstract rather than SQL • Same thing
- Slide 16: Loss of Control • Still programmatic • Use SQL::Abstract rather than SQL • Same thing • (except patches welcome)
- Slide 17: Class::DBI
- Slide 18: Class::DBI Sorry Schwern
- Slide 19: Why DBIx::Class? • I like it. You’ll see why. • TIMTOWDI: • Rose::DB • Alzabo
- Slide 20: Objects • Relations are only a third of an ORM
- Slide 21: Objects • Relations are only a third of an ORM • What’s an object?
- Slide 22: Objects • Relations are only a third of an ORM • What’s an object? • Database columns
- Slide 23: Objects • Relations are only a third of an ORM • What’s an object? • Database columns • Table
- Slide 24: Objects • Relations are only a third of an ORM • What’s an object? • Database columns • Table • Indexes
- Slide 25: A Use Case
- Slide 26: Beer
- Slide 27: Yes, Beer.
- Slide 28: Or... • Beer has many distributers • Beer has many reviews • Beer belongs to a brewer
- Slide 29: Which means... package Beer::Schema::Beer; use base 'DBIx::Class'; __PACKAGE__->load_components( qw|Core| ); __PACKAGE__->table('beer'); __PACKAGE__->add_columns( 'pk1' => { data_type => 'integer', size => 16, is_nullable => 0, is_auto_increment => 1 }, 'name' => { data_type => 'varchar', size => 128, is_nullable => 0 }, 'brewer_pk1' => { data_type => 'integer', size => 16, is_nullable => 0, is_foreign_key => 1 }, ); __PACKAGE__->set_primary_key('pk1'); 1;
- Slide 30: And indexes: __PACKAGE__->add_unique_index(...);
- Slide 31: That gives you: • Deployable SQL (CREATE TABLE, etc) • The foundation for relationships: • $beer->brewer # DTRT
- Slide 32: Managing Relations • A beer is: • made by a brewer • distributed by distributers • reviewed by people
- Slide 33: Simple Relationships belongs_to is the opposite end of has_many
- Slide 34: Simple Relationships belongs_to is the opposite end of has_many has_one, might_have means just that
- Slide 35: Simple Relationships belongs_to is the opposite end of has_many has_one, might_have means just that many_to_many gets complicated
- Slide 36: Creating a relation __PACKAGE__->belongs_to( ‘brewer’, # Accessor ‘Beer::Schema::Brewer’, # Related Class ‘brewer_pk1’ # My Column );
- Slide 37: For simplicity... Brewers, Distributors and Beers are all easy All the same, except Beer has a brewer (brewer_pk1)
- Slide 38: Using it (Manager) use Beer::Schema; my $schema = Beer::Schema ->connect( $dsn );
- Slide 39: $schema # Fetch a result set my $rs = $schema->resultset(‘Beer’);
- Slide 40: Result Sets # Everything is a result set. $rs->count; # How many Beers?
- Slide 41: Everything is a Result Set $rs2 = $rs->search({ name => ‘Stout’ }); $rs2->count; # It chains together.
- Slide 42: Chained Result Sets are what make DBIC Great
- Slide 43: Result Sets return Result Sets $rs->search->search->search- >search->search->search ->search- >search->search->search->search- >search ->search->search->search- >search->search->search ->search- >search->search->search->search- >search ->search->search->search- >search->search->search ->search- >search->search->search->search- >search;
- Slide 44: Why? $rs ->search({ $long_query }) ->search({ $more_filters }) ->search({ $even_more });
- Slide 45: Actual Use: sub active_members { # All profiles that have purchased a membership. my $query = $rs->search( { 'purchase.saved_object_key' => 'membership', 'membership.expiration_date' => \\'>= NOW()' }, { join => { profile_transactions => { 'transaction' => { 'link_transaction_purchase' => { 'purchase' => 'membership' } } }, }, prefetch => [ 'state', 'country', { profile_transactions => { 'transaction' => { 'link_transaction_purchase' => { 'purchase' => 'membership' } } }, } ], group_by => [ qw/membership_id/ ] } ); }
- Slide 46: In SQL: SELECT ... FROM table_profiles me LEFT JOIN profile_transaction profile_transactions ON ( profile_transactions.profile_id = me.profile_id ) JOIN nasa_transactions transaction ON ( transaction.transaction_id = profile_transactions.transaction_id ) LEFT JOIN link_trans_pp link_transaction_purchase ON ( link_transaction_purchase.transaction_id = transaction.transaction_id ) JOIN purchased_products purchase ON ( purchase.purchased_id = link_transaction_purchase.purchased_id ) JOIN nasa_membership membership ON ( membership.membership_id = purchase.saved_product_id ) JOIN state_lookup state ON ( state.state_lookup_id = me.state ) JOIN country_lookup country ON ( country.country_lookup_id = me.country_id ) WHERE ( membership.expiration_date >= NOW() AND purchase.saved_object_key = 'membership' )
- Slide 47: Now: my $query = $schema->resultset(‘Profile’)->active_members; $query->count; # How many? $query->search({ first_name => ‘Bob’ }); # All matching members named Bob $query->search({ first_name => ‘Bob’ })->count; while ( my $profile = $query->next ) { $profile->cars; # Get all of this persons cars } # Clean, no ugly SQL
- Slide 48: Pretty.
- Slide 49: Even More: Managing your schema
- Slide 50: Create Table Statements $schema->create_ddl_dir( [ 'SQLite', 'MySQL', ‘PostgreSQL’ ], $VERSION, \"$destination\" );
- Slide 51: SQLite CREATE TABLE beer ( pk1 INTEGER PRIMARY KEY NOT NULL, name varchar(128) NOT NULL, brewer_pk1 integer(16) NOT NULL );
- Slide 52: DROP TABLE IF EXISTS `beer`; MySQL -- -- Table: `beer` -- CREATE TABLE `beer` ( `pk1` integer(16) NOT NULL auto_increment, `name` varchar(128) NOT NULL, `brewer_pk1` integer(16) NOT NULL, INDEX (`pk1`), INDEX (`brewer_pk1`), PRIMARY KEY (`pk1`), CONSTRAINT `beer_fk_brewer_pk1` FOREIGN KEY (`brewer_pk1`) REFERENCES `brewer` (`pk1`) ON DELETE CASCADE ON UPDATE CASCADE ) Type=InnoDB;
- Slide 53: PostgreSQL -- -- Table: beer -- DROP TABLE beer CASCADE; CREATE TABLE beer ( pk1 bigserial NOT NULL, name character varying(128) NOT NULL, brewer_pk1 bigint NOT NULL, PRIMARY KEY (pk1) );
- Slide 54: Get a working database $schema->deploy; # Yes, it is this simple.
- Slide 55: And now for tests

