1Rose::DB::Object::TutorUisaelr(3C)ontributed Perl DocumeRnotsaet:i:oDnB::Object::Tutorial(3)
2
3
4
6 Rose::DB::Object::Tutorial - A guided tour of the basics of
7 Rose::DB::Object
8
10 This document provides a step-by-step introduction to the
11 Rose::DB::Object module distribution. It demonstrates all of the
12 important features using a semi-realistic example database. This
13 tutorial does not replace the actual documentation for each module,
14 however. The "reference" documentation found in each ".pm" file is
15 still essential, and contains some good examples of its own.
16
17 This tutorial provides a gradual introduction to Rose::DB::Object. It
18 also describes "best practices" for using Rose::DB::Object in the most
19 robust, maintainable manner. If you're just trying to get a feel for
20 what's possible, you can skip to the end and take a look at the
21 completed example database and associated Perl code. But I recommend
22 reading the tutorial from start to finish at least once.
23
24 The examples will start simple and get progressively more complex.
25 You, the developer, have to decide which level of complexity or
26 abstraction is appropriate for your particular task.
27
29 Some of the examples in this tutorial will use the fictional "My::"
30 namespace prefix. Some will use no prefix at all. Your code should
31 use whatever namespace you deem appropriate. Usually, it will be
32 something like "MyCorp::MyProject::" (i.e., your corporation,
33 organization, and/or project). I've chosen to use "My::" or to omit
34 the prefix entirely simply because this produces shorter class names,
35 which will help this tutorial stay within an 80-column width.
36
37 For the sake of brevity, the "use strict" directive and associated "my"
38 declarations have also been omitted from the example code. Needless to
39 say, you should always "use strict" in your actual code.
40
41 Similarly, the traditional "1;" true value used at the end of each
42 ".pm" file has been omitted from the examples. Don't forget to add
43 this to the end of your actual Perl module files.
44
45 Although most of the examples in this tutorial use the base.pm module
46 to set up inheritance, directly modifying the @ISA package variable
47 usually works just as well. In situations where there are circular
48 relationships between classes, the "use base ..." form may be
49 preferable because it runs at compile-time, whereas @ISA modification
50 happens at run-time. In either case, it's a good idea to set up
51 inheritance as early as possible in each module.
52
53 package Product;
54
55 # Set up inheritance first
56 use base qw(Rose::DB::Object);
57
58 # Then do other stuff...
59 ...
60
62 Preface
63 Before doing anything useful with Rose::DB::Object, it's necessary to
64 create and configure a Rose::DB subclass through which
65 Rose::DB::Object-derived objects will access the database.
66
67 To get up to speed quickly with Rose::DB, read the Rose::DB::Tutorial
68 documentation. The rest of this tutorial will assume the existence of
69 a "My::DB" class created as described in the Rose::DB tutorial. Here's
70 a possible incarnation of the "My::DB" class.
71
72 package My::DB;
73
74 use base qw(Rose::DB);
75
76 __PACKAGE__->use_private_registry;
77
78 __PACKAGE__->register_db(
79 driver => 'pg',
80 database => 'mydb',
81 host => 'localhost',
82 username => 'devuser',
83 password => 'mysecret',
84 );
85
86 Read the Rose::DB tutorial for an explanation of this code.
87
88 The PostgreSQL database will be used in the examples in this tutorial,
89 but the features demonstrated will not be specific to that database.
90 If you are following along with a different database, you may have to
91 adjust the specific syntax used in the SQL table creation statements,
92 but all of the same features should be present in some form.
93
94 This tutorial is based on a fictional database schema for a store-like
95 application. Both the database schema the corresponding Perl classes
96 will evolve over the course of this document.
97
98 Getting started
99 Let's start with a single table in our fictional store database.
100
101 CREATE TABLE products
102 (
103 id SERIAL NOT NULL PRIMARY KEY,
104 name VARCHAR(255) NOT NULL,
105 price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
106
107 UNIQUE(name)
108 );
109
110 Here's a basic Rose::DB::Object class to front that table:
111
112 package Product;
113
114 use base qw(Rose::DB::Object);
115
116 __PACKAGE__->meta->setup
117 (
118 table => 'products',
119 columns => [ qw(id name price) ],
120 pk_columns => 'id',
121 unique_key => 'name',
122 );
123
124 The steps are simple:
125
126 1. Inherit from Rose::DB::Object.
127 2. Name the table.
128 3. Name the columns.
129 4. Name the primary key column(s).
130 5. Add unique keys (if any).
131 6. Initialize. (Implied at the end of the setup call)
132
133 Operations 2 through 6 are done through the setup method on the
134 metadata object associated with this class. The table must have a
135 primary key, and may have zero or more unique keys. The primary key
136 and each unique key may contain multiple columns.
137
138 Of course, earlier it was established that Rose::DB needs to be set up
139 for any Rose::DB::Object class to work properly. To that end, this
140 tutorial assumes the existence of a Rose::DB subclass named My::DB that
141 is set up according to the best practices of Rose::DB. We need to make
142 the "Product" class use My::DB. Here's one way to do it:
143
144 package Product;
145
146 use My::DB;
147
148 use base qw(Rose::DB::Object);
149
150 __PACKAGE__->meta->setup
151 (
152 table => 'products',
153 columns => [ qw(id name price) ],
154 pk_columns => 'id',
155 unique_key => 'name',
156 );
157
158 sub init_db { My::DB->new }
159
160 Now "Product" will create a My::DB object when it needs to connect to
161 the database.
162
163 Note that the "My::DB->new" call in init_db() means that each "Product"
164 object will have its own, private "My::DB" object. See the section
165 below, "A brief digression: database objects", for an explanation of
166 this setup and some alternatives.
167
168 Setting up your own base class
169
170 Looking forward, it's likely that all of our Rose::DB::Object-derived
171 classes will want to use My::DB objects when connecting to the
172 database. It's tedious to repeat this code in all of those classes. A
173 common base class can provide a single, shared location for that code.
174
175 package My::DB::Object;
176
177 use My::DB;
178
179 use base qw(Rose::DB::Object);
180
181 sub init_db { My::DB->new }
182
183 (Again, note that all "My::DB::Object"-derived objects will get their
184 own "My::DB" objects given this definition of init_db(). See the
185 "digression" section below for more information.)
186
187 Now the "Product" class can inherit from "My::DB::Object" instead of
188 inheriting from Rose::DB::Object directly.
189
190 package Product;
191
192 use base 'My::DB::Object';
193
194 __PACKAGE__->meta->setup
195 (
196 table => 'products',
197 columns => [ qw(id name price) ],
198 pk_columns => 'id',
199 unique_key => 'name',
200 );
201
202 This use of a common base class is strongly recommended. You will see
203 this pattern repeated in the Rose::DB tutorial as well. The creation
204 of seemingly "trivial" subclasses is a cheap and easy way to ensure
205 ease of extensibility later on.
206
207 For example, imagine we want to add a copy() method to all of our
208 database objects. If they all inherit directly from
209 "Rose::DB::Object", that's not easy to do. But if they all inherit
210 from "My::DB::Object", we can just add the copy() method to that class.
211
212 The lesson is simple: when in doubt, subclass. A few minutes spent now
213 can save you a lot more time down the road.
214
215 Rose::DB::Object in action
216
217 Now that we have our "Product" class all set up, let's see what we can
218 do with it.
219
220 Get and set column values
221
222 By default, each column has a combined accessor/mutator method. When
223 passed a value, the column value is set and returned. When called with
224 no arguments, the value is simply returned.
225
226 $p->name('Bike'); # set name
227 print $p->name; # get name
228
229 Since Rose::DB::Object inherits from Rose::Object, each object method
230 is also a valid constructor argument.
231
232 $p = Product->new(name => 'Cane', price => 1.99);
233 print $p->price; # 1.99
234
235 Load
236
237 An object can be loaded based on a primary key.
238
239 $p = Product->new(id => 1); # primary key
240 $p->load; # Load the object from the database
241
242 An object can also be loaded based on a unique key:
243
244 $p = Product->new(name => 'Sled'); # unique key
245 $p->load; # Load the object from the database
246
247 If there is no row in the database table with the specified primary or
248 unique key value, the call to load() will fail. Under the default
249 error mode, an exception will be thrown. To safely check whether or
250 not such a row exists, use the "speculative" parameter.
251
252 $p = Product->new(id => 1);
253
254 unless($p->load(speculative => 1))
255 {
256 print "No such product with id = 1";
257 }
258
259 Regardless of the error mode, load() will simply return true or false
260 when the "speculative" parameter is used.
261
262 Insert
263
264 To insert a row, create an object and then save it.
265
266 $p = Product->new(id => 123, name => 'Widget', price => 4.56);
267 $p->save; # Insert the object into the database
268
269 The default error mode will throw an exception if anything goes wrong
270 during the save, so we don't have to check the return value.
271
272 Here's another variation:
273
274 $p = Product->new(name => 'Widget', price => 1.23);
275 $p->save;
276
277 print $p->id; # print the auto-generated primary key value
278
279 Since the primary key of the "products" table, "id", is a SERIAL
280 column, a new primary key value will be automatically generated if one
281 is not specified. After the object is saved, we can retrieve the auto-
282 generated value.
283
284 Update
285
286 To update a row, simply save an object that has been previously loaded
287 or saved.
288
289 $p1 = Product->new(name => 'Sprocket', price => 9.99);
290 $p1->save; # Insert a new object into the database
291
292 $p1->price(12.00);
293 $p1->save; # Update the object in the database
294
295 $p2 = Product->new(id => 1);
296 $p2->load; # Load an existing object
297
298 $p2->name($p2->name . ' Mark II');
299 $p2->save; # Update the object in the database
300
301 Delete
302
303 An object can be deleted based on a primary key or a unique key.
304
305 $p = Product->new(id => 1); # primary key
306 $p->delete; # Delete the object from the database
307
308 $p = Product->new(name => 'Sled'); # unique key
309 $p->delete; # Delete the object from the database
310
311 The delete method will return true if the row was deleted or did not
312 exist, false otherwise.
313
314 It works just as well with objects that have been loaded or saved.
315
316 $p1 = Product->new(name => 'Sprocket', price => 9.99);
317 $p1->save; # Insert a new object into the database
318 $p1->delete; # Now delete the object
319
320 $p2 = Product->new(id => 1);
321 $p2->load; # Load an existing object
322 $p2->delete; # Now delete the object
323
324 Multiple objects
325
326 The examples above show SELECT, INSERT, UPDATE, and DELETE operations
327 on one row at time based on primary or unique keys. What about
328 manipulating rows based on other criteria? What about manipulating
329 multiple rows simultaneously? Enter Rose::DB::Object::Manager, or just
330 "the manager" for short.
331
332 But why is there a separate class for dealing with multiple objects?
333 Why not simply add more methods to the object itself? Say, a search()
334 method to go alongside load(), save(), delete() and friends? There are
335 several reasons.
336
337 First, it's somewhat "semantically impure" for the class that
338 represents a single row to also be the class that's used to fetch
339 multiple rows. It's also important to keep the object method namespace
340 as sparsely populated as possible. Each new object method prevents a
341 column with the same name from using that method name.
342 Rose::DB::Object tries to keep the list of reserved method names as
343 small as possible.
344
345 Second, inevitably, classes grow. It's important for the object
346 manager class to be separate from the object class itself so each class
347 can grow happily in isolation, with no potential for namespace or
348 functionality clashes.
349
350 All of that being said, Rose::DB::Object::Manager does include support
351 for adding manager methods to the object class. Obviously, this
352 practice is not recommended, but it exists if you really want it.
353
354 Anyway, let's see some examples. Making a manager class is simply a
355 matter of inheriting from Rose::DB::Object::Manager, specifying the
356 object class, and then creating a series of appropriately named wrapper
357 methods.
358
359 package Product::Manager;
360
361 use base qw(Rose::DB::Object::Manager);
362
363 sub object_class { 'Product' }
364
365 __PACKAGE__->make_manager_methods('products');
366
367 The call to make_manager_methods() creates the following methods:
368
369 get_products
370 get_products_iterator
371 get_products_count
372 delete_products
373 update_products
374
375 The names are pretty much self-explanatory. You can read the
376 Rose::DB::Object::Manager documentation for all the gory details. The
377 important thing to note is that the methods were all named based on the
378 "products" argument to make_manager_methods(). You can see how
379 "products" has been incorporated into each of the method names.
380
381 This naming scheme is just a suggestion. You can name these methods
382 anything you want (using the "methods" parameter to the
383 make_manager_methods() call), or you can even write the methods
384 yourself. Each of these methods is a merely a thin wrapper around the
385 generically-named methods in Rose::DB::Object::Manager. The wrappers
386 pass the specified object class to the generic methods.
387
388 The Perl code for the "Product::Manager" class shown above can be
389 generated automatically by calling the perl_manager_class method on the
390 Rose::DB::Object::Metadata that's associated with the "Product" class.
391 Similarly, the make_manager_class method called on the "Product"
392 metadata object will both generate the code and evaluate it for you,
393 automating the entire process of creating a manager class from within
394 your Rose::DB::Object-derived class.
395
396 package Product;
397
398 use base qw(Rose::DB::Object);
399 ...
400
401 # This actually creates the Product::Manager class
402 # as shown in the code sample above.
403 __PACKAGE__->meta->make_manager_class('products');
404
405 As the comment says, the call to make_manager_class will create a
406 standalone "Product::Manager" class in memory. See the documentation
407 for the perl_manager_class and make_manager_class methods for more
408 information.
409
410 If you decide not to heed my advice, but instead decide to create these
411 methods inside your Rose::DB::Object-derived class directly, you can do
412 so by calling make_manager_methods() from within your object class.
413
414 package Product;
415
416 use Rose::DB::Object::Manager;
417
418 use base 'My::DB::Object';
419 ...
420 Rose::DB::Object::Manager->make_manager_methods('products');
421
422 This will be the last you see of this technique in this tutorial. All
423 of the examples will assume that the recommended approach is used
424 instead.
425
426 Fetching objects
427
428 The most common task for the manager is fetching multiple objects.
429 We'll use the get_products() method to do that. It's based on the
430 get_objects() method, which takes many parameters.
431
432 One (optional) parameter is the now-familiar db object used to connect
433 to the database. This parameter is valid for all
434 Rose::DB::Object::Manager methods. In the absence of this parameter,
435 the init_db() method of the object class will be called in order to
436 create one.
437
438 Passing no arguments at all will simply fetch every "Product" object in
439 the database.
440
441 $products = Product::Manager->get_products();
442
443 foreach my $product (@$products)
444 {
445 print $product->name, "\n";
446 }
447
448 The return value is a reference to an array of "Product" objects. Now
449 let's go to the other extreme.
450
451 $products =
452 Product::Manager->get_products(
453 query =>
454 [
455 name => { like => '%Hat' },
456 id => { ge => 7 },
457 or =>
458 [
459 price => 15.00,
460 price => { lt => 10.00 },
461 ],
462 ],
463 sort_by => 'name',
464 limit => 10,
465 offset => 50);
466
467 That call produces SQL that looks something like this:
468
469 SELECT id, name, price FROM products WHERE
470 name LIKE '%Hat' AND
471 id >= 7 AND
472 (price = 15.00 OR price < 10.00)
473 ORDER BY name
474 LIMIT 10 OFFSET 50
475
476 Manager queries support nested boolean logic and several different
477 kinds of comparison operators. For a full explanation of all the
478 options, see the Rose::DB::Object::Manager documentation.
479
480 The iterator method takes the same kinds of arguments, but returns an
481 iterator that will fetch the objects from the database one at a time.
482
483 $iterator = Product::Manager->get_products_iterator(...);
484
485 while($product = $iterator->next)
486 {
487 print $product->id, ' ', $product->name, "\n";
488
489 $iterator->finish if(...); # exit early?
490 }
491
492 print $iterator->total; # total iterated over
493
494 Note that this is a "real" iterator. Objects not iterated over are not
495 fetched from the database at all.
496
497 Counting objects
498
499 Counting objects is straightforward. The get_products_count() method
500 takes the same kinds of arguments as get_products() and
501 get_products_iterator(). It returns the count.
502
503 $num_cheap_products =
504 Product::Manager->get_products_count(
505 query => [ price => { lt => 1.00 } ]);
506
507 Deleting objects
508
509 The delete_products() method accepts the same kinds of "query"
510 arguments as the manager methods described above, only it uses the
511 parameter name "where" instead.
512
513 $num_rows_deleted =
514 Product::Manager->delete_products(
515 where =>
516 [
517 id => { ne => 123 },
518 name => { like => 'Wax%' },
519 ]);
520
521 Updating objects
522
523 The update_products() method accepts the same kinds of arguments as the
524 delete_products() method, plus a "set" parameter to specify the actual
525 update information.
526
527 $num_rows_updated =
528 Product::Manager->update_products(
529 set =>
530 {
531 price => 5.00,
532 },
533 where =>
534 [
535 price => 4.99,
536 id => { gt => 100 },
537 ]);
538
539 The end of the beginning
540
541 This section has covered the bare minimum usage and functionality of
542 the Rose::DB::Object module distribution. Using these features alone,
543 you can automate the basic CRUD operations (Create, Retrieve, Update,
544 and Delete) for single or multiple objects. But it's almost a shame to
545 stop at this point. There's a lot more that Rose::DB::Object can do
546 for you. The "sweet spot" of effort vs. results is much farther along
547 the curve.
548
549 In the next section, we will expand upon our "Product" class and tap
550 more of Rose::DB::Object's features. But first...
551
552 A brief digression: database objects
553
554 The Rose::DB-derived database object used by each
555 Rose::DB::Object-derived object is available via the db object
556 attribute.
557
558 $p = Product->new(...);
559 $db = $p->db; # My::DB object
560
561 You can read the Rose::DB documentation to explore the capabilities of
562 these db objects. Most of the time, you won't have to be concerned
563 about them. But it's sometime useful to deal with them directly.
564
565 The first thing to understand is where the database object comes from.
566 If the db attribute doesn't exist, it is created by calling init_db().
567 The typical init_db() method simply builds a new database object and
568 returns it. (See the Rose::DB tutorial for an explanation of the
569 possible arguments to new(), and why there are none in the call below.)
570
571 package Product;
572 ...
573 sub init_db { My::DB->new }
574
575 This means that each "Product" object will have its own "My::DB"
576 object, and therefore (in the absence of modules like Apache::DBI) its
577 own connection to the database.
578
579 If this not what you want, you can make init_db() return the same
580 "My::DB" object to every "Product" object. This will make it harder to
581 ensure that the database handle will be closed when all "Product"
582 objects go out of scope, but that may not be important for your
583 application. The easiest way to do this is to call new_or_cached
584 instead of new.
585
586 package Product;
587 ...
588 sub init_db { My::DB->new_or_cached }
589
590 Since init_db() is only called if a "Product" object does not already
591 have a db object, another way to share a single "My::DB" object with
592 several "Product" objects is to do so explicitly, either by pre-
593 creating the "My::DB" object:
594
595 $db = My::DB->new; # will share this db with the Products below
596
597 $p1 = Product->new(db => $db, ...);
598 $p2 = Product->new(db => $db, ...);
599 $p3 = Product->new(db => $db, ...);
600
601 or by letting one of the "Product" objects provide the db for the rest.
602
603 $p1 = Product->new(...);
604 $p2 = Product->new(db => $p1->db, ...); # use $p1's db
605 $p3 = Product->new(db => $p1->db, ...); # use $p1's db
606
607 A note for mod_perl users: when using Apache::DBI, even if each
608 "Product" has its own "My::DB" object, remember that they will all
609 share a single underlying DBI database handle. That is, each
610 Rose::DB-derived object of a given type and domain will eventually call
611 DBI's connect() method with the same arguments, and therefore return
612 the same, cached database handle when running under Apache::DBI. The
613 default cache implementation underlying the new_or_cached method is
614 also mod_perl-aware and will cooperate with Apache::DBI.
615
616 Here's an example where sharing a database object is important:
617 creating several "Product" objects in a single transaction.
618
619 $db = My::DB->new;
620
621 $db->begin_work; # Start transaction
622
623 # Use this $db with each product object
624
625 $p1 = Product->new(name => 'Bike', db => $db);
626 $p1->save;
627
628 $p2 = Product->new(name => 'Sled', db => $db);
629 $p2->save;
630
631 $p3 = Product->new(name => 'Kite', db => $db);
632 $p3->save;
633
634 if(...) # Now either commit them all or roll them all back
635 {
636 $db->commit;
637 }
638 else
639 {
640 $db->rollback;
641 }
642
643 Cross-database migration is another important use for explicitly shared
644 db objects. Here's how to move a product from a production database to
645 an archive database.
646
647 $production_db = My::DB->new('production');
648 $archive_db = My::DB->new('archive');
649
650 # Load bike from production database
651 $p = Product->new(name => 'Bike', db => $production_db);
652 $p->load;
653
654 # Save the bike into the archive database
655 $p->db($archive_db);
656 $p->save(insert => 1); # force an insert instead of an update
657
658 # Delete the bike from the production database
659 $p->db($production_db);
660 $p->delete;
661
662 Mainstream usage
663 Let's imagine that the "products" table has expanded. It now looks
664 like this.
665
666 CREATE TABLE products
667 (
668 id SERIAL NOT NULL PRIMARY KEY,
669 name VARCHAR(255) NOT NULL,
670 price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
671
672 status VARCHAR(128) NOT NULL DEFAULT 'inactive'
673 CHECK(status IN ('inactive', 'active', 'defunct')),
674
675 date_created TIMESTAMP NOT NULL DEFAULT NOW(),
676 release_date TIMESTAMP,
677
678 UNIQUE(name)
679 );
680
681 We could do a straightforward expansion of the "Product" class as
682 designed in the previous section.
683
684 package Product;
685
686 use base 'My::DB::Object';
687
688 __PACKAGE__->meta->setup
689 (
690 table => 'products',
691 columns => [ qw(id name price status date_created release_date) ],
692 pk_columns => 'id',
693 unique_key => 'name',
694 );
695
696 But now we're faced with a few problems. First, while the "status"
697 column only accepts a few pre-defined values, our "Product" object will
698 gladly accept any status value. But maybe that's okay because the
699 database will reject invalid values, causing an exception will be
700 thrown when the object is saved.
701
702 The date/time fields are more troubling. What is the format of a valid
703 value for a TIMESTAMP column in PostgreSQL? Consulting the PostgreSQL
704 documentation will yield the answer, I suppose. But now all the code
705 that uses "Product" objects has to be sure to format the "date_created"
706 and "release_date" values accordingly. That's even more difficult if
707 some of those values come from external sources, such as a web form.
708
709 Worse, what if we decide to change databases in the future? We'd have
710 to hunt down every single place where a "date_created" or
711 "release_date" value is set and then modify the formatting to match
712 whatever format the new database wants. Oh, and we'll have to look
713 that up too. Blah.
714
715 Finally, what about all those default values? The "price" column
716 already had a default value, but now two more columns also have
717 defaults. True, the database will take care of this when a row is
718 inserted, but now the Perl object is diverging more and more from the
719 database representation.
720
721 Let's solve all of these problems. If we more accurately describe the
722 columns, Rose::DB::Object will do the rest.
723
724 package Product;
725
726 use base 'My::DB::Object';
727
728 __PACKAGE__->meta->setup
729 (
730 table => 'products',
731
732 columns =>
733 [
734 id => { type => 'serial', primary_key => 1, not_null => 1 },
735 name => { type => 'varchar', length => 255, not_null => 1 },
736
737 price =>
738 {
739 type => 'decimal',
740 precision => 10,
741 scale => 2,
742 not_null => 1,
743 default => 0.00
744 },
745
746 status =>
747 {
748 type => 'varchar',
749 length => 128,
750 not_null => 1,
751 default => 'inactive',
752 check_in => [ 'inactive', 'active', 'defunct' ],
753 },
754
755 date_created => { type => 'timestamp', not_null => 1,
756 default => 'now()' },
757 release_date => { type => 'timestamp' },
758 ],
759
760 unique_key => 'name',
761
762 allow_inline_column_values => 1,
763 );
764
765 Before examining what new functionality this new class gives us, there
766 are a few things to note about the definition. First, the primary key
767 is no longer specified with the primary_key_columns() method. Instead,
768 the "id" column has its "primary_key" attribute set to a true value in
769 its description.
770
771 Second, note the default value for the "date_created" column. It's a
772 string containing a call to the PL/SQL function now(), which can
773 actually only be run within the database. But thanks to the
774 allow_inline_column_values attribute being set to a true value,
775 Rose::DB::Object will pass the string "now()" through to the database
776 as-is.
777
778 In the case of "creation date" columns like this, it's often better to
779 let the database provide the value as close as possible to the very
780 moment the row is created. On the other hand, this will mean that any
781 newly created "Product" object will have a "strange" value for that
782 column (the string "now()") until/unless it is re-loaded from the
783 database. It's a trade-off.
784
785 Let's see the new "Product" class in action. The defaults work as
786 expected.
787
788 $p = Product->new;
789
790 print $p->status; # 'inactive'
791 print $p->price; # 0.00
792
793 The "status" method now restricts its input, throwing an exception if
794 the input is invalid.
795
796 $p->status('nonesuch'); # Boom! Invalid status: 'nonesuch'
797
798 The timestamp columns now accept any value that Rose::DateTime::Util's
799 parse_date() method can understand.
800
801 $p->release_date('2005-01-22 18:00:57');
802 $p->release_date('12/24/1980 10am');
803
804 See the Rose::DateTime::Util documentation for a full list of
805 acceptable formats.
806
807 Inside a "Product" object, date/time information is stored in DateTime
808 objects.
809
810 $dt = $p->release_date; # DateTime object
811
812 Since DateTime objects can be modified in-place, doing a formerly
813 thorny task like date math is now trivial.
814
815 $p->release_date->add(days => 1);
816
817 The release_date() method also accepts a DateTime object as an input,
818 of course:
819
820 $p->release_date(DateTime->new(...));
821
822 There are even a few convenience functions triggered by passing a
823 name/value pair.
824
825 # Thursday, December 25th 1980 at 10:00:00 AM
826 print $p->release_date(format => '%A, %B %E %Y at %t');
827
828 # Clone the DateTime object, truncate the clone, and return it
829 $month_start = $p->release_date(truncate => 'month');
830
831 print $month_start->strftime('%Y-%m-%d'); # 1980-12-01
832
833 Conveniently, Rose::DB::Object::Manager queries can also use any values
834 that the corresponding column methods will accept. For example, here's
835 a query that filters on the "release_date" column using a DateTime
836 object.
837
838 $last_week = DateTime->now->subtract(weeks => 1);
839
840 $products =
841 Product::Manager->get_products(
842 query =>
843 [
844 release_date => { lt => $last_week },
845 ],
846 sort_by => 'release_date');
847
848 The upshot is that you no longer have to be concerned about the details
849 of the date/time format(s) understood by the underlying database.
850 You're also free to use DateTime objects as a convenient interchange
851 format in your code.
852
853 This ability isn't just limited to date/time columns. Any data type
854 that requires special formatting in the database, and/or is more
855 conveniently dealt with as a more "rich" value on the Perl side of the
856 fence is fair game for this treatment.
857
858 Some other examples include the bitfield column type, which is
859 represented by a Bit::Vector object on the Perl side, and the boolean
860 column type which evaluates the "truth" of its arguments and coerces
861 the value accordingly. In all cases, column values are automatically
862 formatted as required by the native column data types in the database.
863
864 In some circumstances, Rose::DB::Object can even "fake" a data type for
865 use with a database that does not natively support it. For example,
866 the array column type is natively supported by PostgreSQL, but it will
867 also work with MySQL using a VARCHAR column as a stand-in.
868
869 Finally, if you're concerned about the performance implications of
870 "inflating" column values from strings and numbers into (relatively)
871 large objects, rest assured that such inflation is only done as needed.
872 For example, an object with ten date/time columns can be loaded,
873 modified, and saved without ever creating a single DateTime object,
874 provided that none of the date/time columns were among those whose
875 values were modified.
876
877 Put another way, the methods that service the columns have an awareness
878 of the producer and consumer of their data. When data is coming from
879 the database, the column methods accept it as-is. When data is being
880 sent to the database, it is formatted appropriately, if necessary. If
881 a column value was not modified since it was loaded from the database,
882 then the value that was loaded is simply returned as-is. In this way,
883 data can make a round-trip without ever being inflated, deflated, or
884 formatted.
885
886 This behavior is not a requirement of all column methods, but it is a
887 recommended practice--one followed by all the column classes that are
888 part of the Rose::DB::Object distribution.
889
890 Auto-initialization and the convention manager
891 The "Product" class set up in the previous section is useful, but it
892 also takes significantly more typing to set up. Over the long term,
893 it's still a clear win. On the other hand, a lot of the details in the
894 column descriptions are already known by the database: column types,
895 default values, maximum lengths, etc. It would be handy if we could
896 ask the database for this information instead of looking it up and
897 typing it in manually.
898
899 This process of interrogating the database in order to extract metadata
900 is called "auto-initialization." There's an entire section of the
901 Rose::DB::Object::Metadata documentation dedicated to the topic. The
902 executive summary is that auto-initialization saves work in the short-
903 run, but with some long-term costs. Read the friendly manual for the
904 details. For the purposes of this tutorial, I will simply demonstrate
905 the features, culminating in the suggested best practice.
906
907 Let's start by applying auto-initialization to the "Product" class.
908
909 package Product;
910
911 use base 'My::DB::Object';
912
913 __PACKAGE__->meta->table('products');
914 __PACKAGE__->meta->auto_initialize;
915
916 Believe it or not, that class is equivalent to the previous
917 incarnation, right down to the details of the columns and the unique
918 key. As long as the table is specified, Rose::DB::Object will dig all
919 the rest of the information out of the database. Handy!
920
921 In fact, that class can be shortened even further with the help of the
922 convention manager.
923
924 package Product;
925
926 use base 'My::DB::Object';
927
928 __PACKAGE__->meta->auto_initialize;
929
930 Now even the table is left unspecified. How does Rose::DB::Object know
931 what to do in this case? Why, by convention, of course. The default
932 convention manager dictates that class names are singular and
933 TitleCased, and their corresponding table names are lowercase and
934 plural. Thus, the omitted table name in the "Product" class is, by
935 convention, assumed to be named "products".
936
937 Like auto-initialization, the convention manager is handy, but may also
938 present some maintenance issues. I tend to favor a more explicitly
939 approach, but I can also imagine scenarios where the convention manager
940 is a good fit.
941
942 Keep in mind that customized convention managers are possible, allowing
943 individual organizations or projects to define their own conventions.
944 You can read all about it in the Rose::DB::Object::ConventionManager
945 documentation.
946
947 Anyway, back to auto-initialization. Yes, auto_initialize() will dig
948 out all sorts of interesting and important information for you.
949 Unfortunately, it will dig that information out every single time the
950 class is loaded. Worse, this class will fail to load at all if a
951 database connection is not immediately available.
952
953 Auto-initialization seems like something that is best done only once,
954 with the results being saved in a more conventional form. That's just
955 what Rose::DB::Object::Metadata's code generation functions are
956 designed to do. The "perl_*" family of methods can generate snippets
957 of Perl code, or even entire classes, based on the results of the auto-
958 initialization process. They'll even honor some basic code formatting
959 directives.
960
961 package Product;
962
963 use base 'My::DB::Object';
964
965 __PACKAGE__->meta->table('products');
966 __PACKAGE__->meta->auto_initialize;
967
968 print __PACKAGE__->meta->perl_class_definition(indent => 2,
969 braces => 'bsd');
970
971 Here's the output of that print statement. A few long lines were
972 manually wrapped, but it's otherwise unmodified.
973
974 package Product;
975
976 use strict;
977
978 use base 'My::DB::Object';
979
980 __PACKAGE__->meta->setup
981 (
982 table => 'products',
983
984 columns =>
985 [
986 id => { type => 'integer', not_null => 1 },
987 name => { type => 'varchar', length => 255, not_null => 1 },
988 price => { type => 'numeric', default => '0.00',
989 not_null => 1, precision => 10, scale => 2 },
990 vendor_id => { type => 'integer' },
991 status => { type => 'varchar', default => 'inactive',
992 length => 128, not_null => 1 },
993 date_created => { type => 'timestamp', default => 'now()',
994 not_null => 1 },
995 release_date => { type => 'timestamp' },
996 ],
997
998 primary_key_columns => [ 'id' ],
999
1000 unique_keys => [ 'name' ],
1001
1002 allow_inline_column_values => 1,
1003 );
1004
1005 1;
1006
1007 Copy and paste that output back into the "Product.pm" file and you're
1008 in business.
1009
1010 The door is open to further automation through scripts that call the
1011 methods demonstrated above. Although it's my inclination to work
1012 towards a static, explicit type of class definition, the tools are
1013 there for those who prefer a more dynamic approach.
1014
1015 Foreign keys
1016 When a column in one table references a row in another table, the
1017 referring table is said to have a "foreign key." As with primary and
1018 unique keys, Rose::DB::Object supports foreign keys made up of more
1019 than one column.
1020
1021 In the context of Rose::DB::Object, a foreign key is a database-
1022 supported construct that ensures that any non-null value in a foreign
1023 key column actually refers to an existing row in the foreign table.
1024 Databases that enforce this constraint are said to support "referential
1025 integrity." Foreign keys are only applicable to
1026 Rose::DB::Object-derived classes when the underlying database supports
1027 "native" foreign keys and enforces referential integrity.
1028
1029 While it's possible to define foreign keys in a
1030 Rose::DB::Object-derived class even if there is no support for them in
1031 the database, this is considered bad practice. If you're just trying
1032 to express some sort of relationship between two tables, there's a more
1033 appropriate way to do so. (More on that in the next section.)
1034
1035 Let's add a foreign key to the "products" table. First, we'll need to
1036 create the table that the foreign key will reference.
1037
1038 CREATE TABLE vendors
1039 (
1040 id SERIAL NOT NULL PRIMARY KEY,
1041 name VARCHAR(255) NOT NULL,
1042
1043 UNIQUE(name)
1044 );
1045
1046 When dealing with any kind of inter-table relationship,
1047 Rose::DB::Object requires a Rose::DB::Object-derived class fronting
1048 each participating table. So we need a class for the "vendors" table.
1049
1050 package Vendor;
1051
1052 use base 'My::DB::Object';
1053
1054 __PACKAGE__->meta->setup
1055 (
1056 table => 'vendors',
1057 columns =>
1058 [
1059 id => { type => 'serial', primary_key => 1, not_null => 1 },
1060 name => { type => 'varchar', length => 255, not_null => 1 },
1061 ],
1062 unique_key => 'name',
1063 );
1064
1065 Now we'll add the foreign key to our ever-growing "products" table.
1066
1067 CREATE TABLE products
1068 (
1069 id SERIAL NOT NULL PRIMARY KEY,
1070 name VARCHAR(255) NOT NULL,
1071 price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
1072
1073 vendor_id INT REFERENCES vendors (id),
1074
1075 status VARCHAR(128) NOT NULL DEFAULT 'inactive'
1076 CHECK(status IN ('inactive', 'active', 'defunct')),
1077
1078 date_created TIMESTAMP NOT NULL DEFAULT NOW(),
1079 release_date TIMESTAMP,
1080
1081 UNIQUE(name)
1082 );
1083
1084 Finally, here's how the foreign key definition looks in the Perl class.
1085
1086 package Product;
1087
1088 use base 'My::DB::Object';
1089
1090 __PACKAGE__->meta->setup
1091 (
1092 table => 'products',
1093
1094 columns =>
1095 [
1096 id => { type => 'integer', not_null => 1 },
1097 name => { type => 'varchar', length => 255, not_null => 1 },
1098 price => { type => 'numeric', default => '0.00',
1099 not_null => 1, precision => 10, scale => 2 },
1100 vendor_id => { type => 'integer' },
1101 status => { type => 'varchar', default => 'inactive',
1102 length => 128, not_null => 1 },
1103 date_created => { type => 'timestamp', default => 'now()',
1104 not_null => 1 },
1105 release_date => { type => 'timestamp' },
1106 ],
1107
1108 primary_key_columns => [ 'id' ],
1109
1110 unique_keys => [ 'name' ],
1111
1112 allow_inline_column_values => 1,
1113
1114 foreign_keys =>
1115 [
1116 vendor =>
1117 {
1118 class => 'Vendor',
1119 key_columns => { vendor_id => 'id' },
1120 },
1121 ],
1122 );
1123
1124 Note that a "vendor_id" column is added to the column list. This needs
1125 to be done independently of any foreign key definition. It's a new
1126 column, so it needs to be in the column list. There's nothing more to
1127 it than that.
1128
1129 There's also the foreign key definition itself. The name/hashref-value
1130 pair passed to the foreign_keys() method is (roughly) shorthand for
1131 this.
1132
1133 Rose::DB::Object::Metadata::ForeignKey->new(
1134 name => 'vendor',
1135 class => 'Vendor',
1136 key_columns => { vendor_id => 'id' });
1137
1138 In other words, "vendor" is the name of the foreign key, and the rest
1139 of the information is used to set attributes on the foreign key object.
1140 You could, in fact, construct your own foreign key objects and pass
1141 them to foreign_keys() (or add_foreign_keys(), etc.) but that would
1142 require even more typing.
1143
1144 Going in the other direction, since our class and column names match up
1145 with what the convention manager expects, we could actually shorten the
1146 foreign key setup code to this.
1147
1148 foreign_keys => [ 'vendor' ],
1149
1150 Given only a foreign key name, the convention manager will derive the
1151 "Vendor" class name and will find the "vendor_id" column in the
1152 "Product" class and match it up to the primary key of the "vendors"
1153 table. As with most things in Rose::DB::Object class setup, you can be
1154 as explicit or as terse as you feel comfortable with, depending on how
1155 closely you conform to the expected conventions.
1156
1157 So, what does this new "vendor" foreign key do for us? Let's add some
1158 data and see. Imagine the following two objects.
1159
1160 $v = Vendor->new(name => 'Acme')->save;
1161 $p = Product->new(name => 'Kite')->save;
1162
1163 Note the use of the idiomatic way to create and then save an object in
1164 "one step." This is possible because both the new and save methods
1165 return the object itself. Anyway, let's link the two objects. One way
1166 to do it is to set the column values directly.
1167
1168 $p->vendor_id($v->id);
1169 $p->save;
1170
1171 To use this technique, we must know which columns link to which other
1172 columns, of course. But it works. We can see this by calling the
1173 method named after the foreign key itself: vendor().
1174
1175 $v = $p->vendor; # Vendor object
1176 print $v->name; # "Acme"
1177
1178 The vendor() method can be used to link the two objects as well. Let's
1179 start over and try it that way:
1180
1181 $v = Vendor->new(name => 'Smith')->save;
1182 $p = Product->new(name => 'Knife')->save;
1183
1184 $p->vendor($v);
1185 $p->save;
1186
1187 print $p->vendor->name; # "Smith"
1188
1189 Remember that there is no column named "vendor" in the "products"
1190 table. There is a "vendor_id" column, which has its own vendor_id()
1191 get/set method that accepts and returns an integer value, but that's
1192 not what we're doing in the example above. Instead, we're calling the
1193 vendor() method, which accepts and returns an entire "Vendor" object.
1194
1195 The vendor() method actually accepts several different kinds of
1196 arguments, all of which it inflates into "Vendor" objects. An already-
1197 formed "Vendor" object was passed above, but other formats are
1198 possible. Imagine a new product also made by Smith.
1199
1200 $p = Product->new(name => 'Rope')->save;
1201 $p->vendor(name => 'Smith');
1202 $p->save;
1203
1204 Here the arguments passed to the vendor() method are name/value pairs
1205 which will be used to construct the appropriate "Vendor" object. Since
1206 "name" is a unique key in the "vendors" table, the "Vendor" class can
1207 look up the existing vendor named "Smith" and assign it to the "Rope"
1208 product.
1209
1210 If no vendor named "Smith" existed, one would have been created when
1211 the product was saved. In this case, the save process would take place
1212 within a transaction (assuming the database supports transactions) to
1213 ensure that both the product and vendor are created successfully, or
1214 neither is.
1215
1216 The name/value pairs can also be provided in a reference to a hash.
1217
1218 $p = Product->new(name => 'Rope')->save;
1219 $p->vendor({ name => 'Smith' });
1220 $p->save;
1221
1222 Here's yet another argument format. Imagine that the "Acme" vendor id
1223 is 1.
1224
1225 $p = Product->new(name => 'Crate')->save;
1226 $p->vendor(1);
1227 $p->save;
1228
1229 print $p->vendor->name; # "Acme"
1230
1231 Like the name/value pair argument format, a primary key value will be
1232 used to construct the appropriate object. (This only works if the
1233 foreign table has a single-column primary key, of course.) And like
1234 before, if such an object doesn't exist, it will be created. But in
1235 this case, if no existing vendor object had an "id" of 1, the attempt
1236 to create one would have failed because the "name" column of the
1237 inserted row would have been null.
1238
1239 To summarize, the foreign key method can take arguments in these forms.
1240
1241 • An object of the appropriate class.
1242
1243 • Name/value pairs used to construct such an object.
1244
1245 • A reference to a hash containing name/value pairs used to construct
1246 such an object.
1247
1248 • A primary key value (but only if the foreign table has a single-
1249 column primary key).
1250
1251 In each case, the foreign object will be added to the database it if
1252 does not already exist there. This all happens when the "parent"
1253 ("Product") object is saved. Until then, nothing is stored in the
1254 database.
1255
1256 There's also another method created in response to the foreign key
1257 definition. This one allows the foreign object to be deleted from the
1258 database.
1259
1260 print $p->vendor->name; # "Acme"
1261 $p->delete_vendor();
1262 $p->save; # The "Acme" vendor is deleted from the vendors table
1263
1264 Again, the actual database modification takes place when the parent
1265 object is saved. Note that this operation will fail if any other rows
1266 in the "products" table still reference the Acme vendor. And again,
1267 since this all takes place within a transaction (where supported), the
1268 entire operation will fail or succeed as a single unit.
1269
1270 Finally, if we want to simply disassociate a product from its vendor,
1271 we can simply set the vendor to undef.
1272
1273 $p->vendor(undef); # This product has no vendor
1274 $p->save;
1275
1276 Setting the "vendor_id" column directly has the same effect, of course.
1277
1278 $p->vendor_id(undef); # set vendor_id = NULL
1279 $p->save;
1280
1281 Before moving on to the next section, here's a brief note about auto-
1282 initialization and foreign keys. Since foreign keys are a construct of
1283 the database itself, the auto-initialization process can actually
1284 discover them and create the appropriate foreign key metadata.
1285
1286 Since all of the column and table names are still in sync with the
1287 expected conventions, the "Product" class can still be defined like
1288 this:
1289
1290 package Product;
1291
1292 use base 'My::DB::Object';
1293
1294 __PACKAGE__->meta->auto_initialize;
1295
1296 while retaining all of the abilities demonstrated above.
1297
1298 The perl_class_definition() method will produce the appropriate foreign
1299 key definitions, as expected.
1300
1301 package Product;
1302
1303 use base 'My::DB::Object';
1304
1305 __PACKAGE__->meta->auto_initialize;
1306
1307 print __PACKAGE__->meta->perl_class_definition(indent => 2,
1308 braces => 'bsd');
1309
1310 Here's the output.
1311
1312 package Product;
1313
1314 use base 'My::DB::Object';
1315
1316 __PACKAGE__->meta->setup
1317 (
1318 table => 'products',
1319
1320 columns =>
1321 [
1322 id => { type => 'integer', not_null => 1 },
1323 name => { type => 'varchar', length => 255, not_null => 1 },
1324 price => { type => 'numeric', default => '0.00',
1325 not_null => 1, precision => 10, scale => 2 },
1326 vendor_id => { type => 'integer' },
1327 status => { type => 'varchar', default => 'inactive',
1328 length => 128, not_null => 1 },
1329 date_created => { type => 'timestamp', default => 'now()',
1330 not_null => 1 },
1331 release_date => { type => 'timestamp' },
1332 ],
1333
1334 primary_key_columns => [ 'id' ],
1335
1336 unique_keys => [ 'name' ],
1337
1338 allow_inline_column_values => 1,
1339
1340 foreign_keys =>
1341 [
1342 vendor =>
1343 {
1344 class => 'Vendor',
1345 key_columns => { vendor_id => 'id' },
1346 },
1347 ],
1348 );
1349
1350 1;
1351
1352 Relationships
1353 One-to-one and many-to-one relationships
1354
1355 Foreign keys are a database-native representation of a specific kind of
1356 inter-table relationship. This concept can be further generalized to
1357 encompass other kinds of relationships as well. But before we delve
1358 into that, let's consider the kind of relationship that a foreign key
1359 represents.
1360
1361 In the product and vendor example in the previous section, each product
1362 has one vendor. (Actually it can have zero or one vendor, since the
1363 "vendor_id" column allows NULL values. But for now, we'll leave that
1364 aside.)
1365
1366 When viewed in terms of the participating tables, things look slightly
1367 different. Earlier, we established that several products can have the
1368 same vendor. So the inter-table relationship is actually this: many
1369 rows from the "products" table may refer to one row from the "vendors"
1370 table.
1371
1372 Rose::DB::Object describes inter-table relationships from the
1373 perspective of a given table by using the cardinality of the "local"
1374 table ("products") followed by the cardinality of the "remote" table
1375 ("vendors"). The foreign key in the "products" table (and "Product"
1376 class) therefore represents a "many to one" relationship.
1377
1378 If the relationship were different and each vendor was only allowed to
1379 have a single product, then the relationship would be "one to one."
1380 Given only the foreign key definition as it exists in the database,
1381 it's not possible to determine whether the relationship is "many to
1382 one" or "one to one." The default is "many to one" because that's the
1383 less restrictive choice.
1384
1385 To override the default, a relationship type string can be included in
1386 the foreign key description.
1387
1388 foreign_keys =>
1389 [
1390 vendor =>
1391 {
1392 class => 'Vendor',
1393 key_columns => { vendor_id => 'id' },
1394 relationship_type => 'one to one',
1395 },
1396 ],
1397
1398 (The "relationship_type" parameter may be shortened to "rel_type", if
1399 desired.)
1400
1401 Rose::DB::Object generalizes all inter-table relationships using a
1402 family of aptly named relationship objects. Each inherits from the
1403 Rose::DB::Object::Metadata::Relationship base class.
1404
1405 Even foreign keys are included under the umbrella of this concept.
1406 When foreign key metadata is added to a Rose::DB::Object-derived class,
1407 a corresponding "many to one" or "one to one" relationship is actually
1408 added as well. This relationship is simply a proxy for the foreign
1409 key. It exists so that the set of relationship objects encompasses all
1410 relationships, even those that correspond to foreign keys in the
1411 database. This makes iterating over all relationships in a class a
1412 simple affair.
1413
1414 foreach my $rel (Product->meta->relationships)
1415 {
1416 print $rel->name, ': ', $rel->type, "\n";
1417 }
1418
1419 For the "Product" class, the output is:
1420
1421 vendor: many to one
1422
1423 Given the two possible cardinalities, "many" and "one", it's easy to
1424 come up with a list of all possible inter-table relationships. Here
1425 they are, listed with their corresponding relationship object classes.
1426
1427 one to one - Rose::DB::Object::Metadata::Relationship::OneToOne
1428 one to many - Rose::DB::Object::Metadata::Relationship::OneToMany
1429 many to one - Rose::DB::Object::Metadata::Relationship::ManyToOne
1430 many to many - Rose::DB::Object::Metadata::Relationship::ManyToMany
1431
1432 We've already seen that "one to one" and "many to one" relationships
1433 can be represented by foreign keys in the database, but that's not a
1434 requirement. It's perfectly possible to have either of those two kinds
1435 of relationships in a database that has no native support for foreign
1436 keys. (MySQL using the MyISAM storage engine is a common example.)
1437
1438 If you find yourself using such a database, there's no reason to lie to
1439 your Perl classes by adding foreign key metadata. Instead, simply add
1440 a relationship.
1441
1442 Here's an example of our "Product" class as it might exist on a
1443 database that does not support foreign keys. (The "Product" class is
1444 getting larger now, so previously established portions may be omitted
1445 from now on.)
1446
1447 package Product;
1448
1449 use base 'My::DB::Object';
1450
1451 __PACKAGE__->meta->setup
1452 (
1453 table => 'products',
1454 columns => [... ],
1455 pk_columns => 'id',
1456 unique_key => 'name',
1457
1458 relationships =>
1459 [
1460 vendor =>
1461 {
1462 type => 'many to one',
1463 class => 'Vendor',
1464 column_map => { vendor_id => 'id' },
1465 },
1466 ],
1467 );
1468
1469 They syntax and semantics are similar to those described for foreign
1470 keys. The only slight differences are the names and types of
1471 parameters accepted by relationship objects.
1472
1473 In the example above, a "many to one" relationship named "vendor" is
1474 set up. As demonstrated before, this definition can be reduced much
1475 further, allowing the convention manager to fill in the details. But
1476 unlike the case with the foreign key definition, where only the name
1477 was supplied, we must provide the relationship type as well.
1478
1479 relationships => [ vendor => { type => 'many to one' } ],
1480
1481 There's an even more convenient shorthand for that:
1482
1483 relationships => [ vendor => 'many to one' ],
1484
1485 (Again, this all depends on naming the tables, classes, and columns in
1486 accordance with the expectations of the convention manager.) The
1487 resulting vendor() and delete_vendor() methods behave exactly the same
1488 as the methods created on behalf of the foreign key definition.
1489
1490 One-to-many relationships
1491
1492 Now let's explore the other two relationship types. We'll start with
1493 "one to many" by adding region-specific pricing to our products.
1494 First, we'll need a "prices" table.
1495
1496 CREATE TABLE prices
1497 (
1498 id SERIAL NOT NULL PRIMARY KEY,
1499 product_id INT NOT NULL REFERENCES products (id),
1500 region CHAR(2) NOT NULL DEFAULT 'US',
1501 price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
1502
1503 UNIQUE(product_id, region)
1504 );
1505
1506 This table needs a corresponding Rose::DB::Object-derived class, of
1507 course.
1508
1509 package Price;
1510
1511 use base 'My::DB::Object';
1512
1513 __PACKAGE__->meta->setup
1514 (
1515 table => 'prices',
1516
1517 columns =>
1518 [
1519 id => { type => 'serial', not_null => 1 },
1520 product_id => { type => 'int', not_null => 1 },
1521 region => { type => 'char', length => 2, not_null => 1 },
1522 price =>
1523 {
1524 type => 'decimal',
1525 precision => 10,
1526 scale => 2,
1527 not_null => 1,
1528 default => 0.00
1529 },
1530 ],
1531
1532 primary_key_columns => [ 'id' ],
1533
1534 unique_key => [ 'product_id', 'region' ],
1535
1536 foreign_keys =>
1537 [
1538 product =>
1539 {
1540 class => 'Product',
1541 key_columns => { product_id => 'id' },
1542 },
1543 ],
1544 );
1545
1546 The "price" column can be removed from the "products" table.
1547
1548 ALTER TABLE products DROP COLUMN price;
1549
1550 Finally, the "Product" class needs to be modified to reference the
1551 "prices" table.
1552
1553 package Product;
1554
1555 use base 'My::DB::Object';
1556
1557 use Price;
1558 use Vendor;
1559
1560 __PACKAGE__->meta->setup
1561 (
1562 table => 'products',
1563 columns => [ ... ],
1564 pk_columns => 'id',
1565 unique_key => 'name',
1566
1567 foreign_keys =>
1568 [
1569 vendor =>
1570 {
1571 class => 'Vendor',
1572 key_columns => { vendor_id => 'id' },
1573 },
1574 ],
1575
1576 relationships =>
1577 [
1578 prices =>
1579 {
1580 type => 'one to many',
1581 class => 'Price',
1582 column_map => { id => 'product_id' },
1583 },
1584 ],
1585 );
1586
1587 Note that both the column map for the "one to many" relationship and
1588 the key columns for the foreign key connect "local" columns to
1589 "foreign" columns.
1590
1591 The "vendor_id" column in the local table ("products") is connected to
1592 the "id" column in the foreign table ("vendors"):
1593
1594 vendor =>
1595 {
1596 key_columns => { vendor_id => 'id' },
1597 ...
1598 }
1599
1600 The "id" column in the local table ("products") is connected to the
1601 "product_id" column in the foreign table ("prices"):
1602
1603 prices =>
1604 {
1605 column_map => { id => 'product_id' },
1606 ...
1607 }
1608
1609 This is all from the perspective of the class in which the definitions
1610 appear. Note that things are reversed in the "Price" class.
1611
1612 package Price;
1613 ...
1614 __PACKAGE__->meta->setup
1615 (
1616 ...
1617 foreign_keys =>
1618 [
1619 product =>
1620 {
1621 class => 'Product',
1622 key_columns => { product_id => 'id' },
1623 },
1624 ],
1625 );
1626
1627 Here, the "product_id" column in the local table ("prices") is
1628 connected to the "id" column in the foreign table ("products").
1629
1630 The methods created by "... to many" relationships behave much like
1631 their "... to one" and foreign key counterparts. The main difference
1632 is that lists or references to arrays of the previously described
1633 argument formats are also acceptable, while name/value pairs outside of
1634 a hashref are not.
1635
1636 Here's a list of argument types accepted by "many to one" methods like
1637 "prices".
1638
1639 • A list or reference to an array of objects of the appropriate
1640 class.
1641
1642 • A list or reference to an array of hash references containing
1643 name/value pairs used to construct such objects.
1644
1645 • A list or reference to an array of primary key values (but only if
1646 the foreign table has a single-column primary key).
1647
1648 Setting a new list of prices will delete all the old prices. As with
1649 foreign keys, any actual database modification happens when the parent
1650 object is saved. Here are some examples.
1651
1652 $p = Product->new(name => 'Kite');
1653 $p->prices({ price => 1.23, region => 'US' },
1654 { price => 4.56, region => 'UK' });
1655
1656 $p->save; # database is modified here
1657
1658 # US: 1.23, UK: 4.56
1659 print join(', ', map { $_->region . ': ' . $_->price } $p->prices);
1660
1661 New prices can be added without deleting and resetting the entire list:
1662
1663 # Add two prices to the existing list
1664 $p->add_prices({ price => 7.89, region => 'DE' },
1665 { price => 1.11, region => 'JP' });
1666
1667 $p->save; # database is modified here
1668
1669 Passing a reference to an empty array will cause all the prices to be
1670 deleted:
1671
1672 $p->prices([]); # delete all prices associated with this product
1673 $p->save; # database is modified here
1674
1675 Cascading delete
1676
1677 Deleting a product now becomes slightly more interesting. The naive
1678 approach fails.
1679
1680 $p->delete; # Fatal error!
1681
1682 # DBD::Pg::st execute failed: ERROR: update or delete on "products"
1683 # violates foreign key constraint "prices_product_id_fkey" on
1684 # "prices"
1685 # DETAIL: Key (id)=(12345) is still referenced from table "prices".
1686
1687 Since rows in the "prices" table now link to rows in the "products"
1688 table, a product cannot be deleted until all of the prices that refer
1689 to it are also deleted. There are a few ways to deal with this.
1690
1691 The best solution is to add a trigger to the "products" table itself in
1692 the database that makes sure to delete any associated prices before
1693 deleting a product. This change will allow the naive approach shown
1694 above to work correctly.
1695
1696 A less robust solution is necessary if your database does not support
1697 triggers. One such solution is to manually delete the prices before
1698 deleting the product. This can be done in several ways. The prices
1699 can be deleted directly, like this.
1700
1701 foreach my $price ($p->prices)
1702 {
1703 $price->delete; # Delete all associated prices
1704 }
1705
1706 $p->delete; # Now it's safe to delete the product
1707
1708 The list of prices for the product can also be set to an empty list,
1709 which will have the effect of deleting all associated prices when the
1710 product is saved.
1711
1712 $p->prices([]);
1713 $p->save; # All associated prices deleted here
1714 $p->delete; # Now it's safe to delete the product
1715
1716 Finally, the delete() method can actually automate this process, and do
1717 it all inside a transaction as well.
1718
1719 $p->delete(cascade => 1); # Delete all associated rows too
1720
1721 Again, the recommended approach is to use triggers inside the database
1722 itself. But if necessary, these other approaches will work too.
1723
1724 Many-to-many relationships
1725
1726 The final relationship type is the most complex. In a "many to many"
1727 relationship, a single row in table A may be related to multiple rows
1728 in table B, while a single row in table B may also be related to
1729 multiple rows in table A. (Confused? A concrete example will follow
1730 shortly.)
1731
1732 This kind of relationship involves three tables instead of just two.
1733 The "local" and "foreign" tables, familiar from the other relationship
1734 types described above, still exist, but now there's a third table that
1735 connects rows from those two tables. This third table is called the
1736 "mapping table," and the Rose::DB::Object-derived class that fronts it
1737 is called the "map class."
1738
1739 Let's add such a relationship to our growing family of classes.
1740 Imagine that each product may come in several colors. Right away,
1741 both the "one to one" and "many to one" relationship types are
1742 eliminated since they can only provide a single color for any given
1743 product.
1744
1745 But wait, isn't a "one to many" relationship suitable? After all, one
1746 product may have many colors. Unfortunately, such a relationship is
1747 wasteful in this case. Let's see why. Imagine a "colors" table like
1748 this.
1749
1750 CREATE TABLE colors
1751 (
1752 id SERIAL NOT NULL PRIMARY KEY,
1753 name VARCHAR(255) NOT NULL,
1754 product_id INT NOT NULL REFERENCES products (id)
1755 );
1756
1757 Here's a simple "Color" class to front it.
1758
1759 package Color;
1760
1761 use base 'My::DB::Object';
1762
1763 __PACKAGE__->meta->setup
1764 (
1765 table => 'colors',
1766 columns =>
1767 [
1768 id => { type => 'serial', primary_key => 1, not_null => 1 },
1769 name => { type => 'varchar', length => 255, not_null => 1 },
1770 product_id => { type => 'int', not_null => 1 },
1771 ],
1772
1773 foreign_keys =>
1774 [
1775 product =>
1776 {
1777 class => 'Product',
1778 key_columns => { product_id => 'id' },
1779 },
1780 ],
1781 );
1782
1783 Finally, let's add the "one to many" relationship to the "Product"
1784 class.
1785
1786 package Product;
1787
1788 use base 'My::DB::Object';
1789
1790 __PACKAGE__->meta->setup
1791 (
1792 ...
1793 relationships =>
1794 [
1795 colors =>
1796 {
1797 type => 'one to many',
1798 class => 'Color',
1799 column_map => { id => 'product_id' },
1800 },
1801 ...
1802 ],
1803 );
1804
1805 It works as expected.
1806
1807 $p1 = Product->new(id => 10,
1808 name => 'Sled',
1809 colors =>
1810 [
1811 { name => 'red' },
1812 { name => 'green' },
1813 ]);
1814 $p1->save;
1815
1816 $p2 = Product->new(id => 20,
1817 name => 'Kite',
1818 colors =>
1819 [
1820 { name => 'blue' },
1821 { name => 'green' },
1822 { name => 'red' },
1823 ]);
1824 $p2->save;
1825
1826 But now look at the contents of the "colors" table in the database.
1827
1828 mydb=# select * from colors;
1829
1830 id | name | product_id
1831 ----+-------+------------
1832 1 | red | 10
1833 2 | green | 10
1834 3 | blue | 20
1835 4 | green | 20
1836 5 | red | 20
1837
1838 Notice that the colors "green" and "red" appear twice. Now imagine
1839 that there are 50,000 products. What are the odds that there will be
1840 more than a few colors in common among them?
1841
1842 This is a poor database design. To fix it, we must recognize that
1843 colors will be shared among products, since the set of possible colors
1844 is relatively small compared to the set of possible products. One
1845 product may have many colors, but one color may also belong to many
1846 products. And there you have it: a textbook "many to many"
1847 relationship.
1848
1849 Let's redesign this relationship in "many to many" form, starting with
1850 a new version of the "colors" table.
1851
1852 CREATE TABLE colors
1853 (
1854 id SERIAL NOT NULL PRIMARY KEY,
1855 name VARCHAR(255) NOT NULL,
1856
1857 UNIQUE(name)
1858 );
1859
1860 Since each color will now appear only once in this table, we can make
1861 the "name" column a unique key.
1862
1863 Here's the new "Color" class.
1864
1865 package Color;
1866
1867 use base 'My::DB::Object';
1868
1869 __PACKAGE__->meta->setup
1870 (
1871 table => 'colors',
1872 columns =>
1873 [
1874 id => { type => 'serial', primary_key => 1, not_null => 1 },
1875 name => { type => 'varchar', length => 255, not_null => 1 },
1876 ],
1877
1878 unique_key => 'name',
1879 );
1880
1881 Since the "colors" table no longer has a foreign key that points to the
1882 "products" table, we need some way to connect the two tables: a mapping
1883 table.
1884
1885 CREATE TABLE product_color_map
1886 (
1887 product_id INT NOT NULL REFERENCES products (id),
1888 color_id INT NOT NULL REFERENCES colors (id),
1889
1890 PRIMARY KEY(product_id, color_id)
1891 );
1892
1893 Note that there's no reason for a separate primary key column in this
1894 table. We'll use a two-column primary key instead.
1895
1896 Here's the map class.
1897
1898 package ProductColorMap;
1899
1900 use base 'My::DB::Object';
1901
1902 __PACKAGE__->meta->setup
1903 (
1904 table => 'product_color_map',
1905 columns =>
1906 [
1907 product_id => { type => 'int', not_null => 1 },
1908 color_id => { type => 'int', not_null => 1 },
1909 ],
1910
1911 primary_key_columns => [ 'product_id', 'color_id' ],
1912
1913 foreign_keys =>
1914 [
1915 product =>
1916 {
1917 class => 'Product',
1918 key_columns => { product_id => 'id' },
1919 },
1920
1921 color =>
1922 {
1923 class => 'Color',
1924 key_columns => { color_id => 'id' },
1925 },
1926 ],
1927 );
1928
1929 It's important that the map class have either a foreign key or a "many
1930 to one" relationship pointing to each of the tables that it maps
1931 between. In this case, there are two foreign keys.
1932
1933 Finally, here's the "many to many" relationship definition in the
1934 "Product" class.
1935
1936 package Product;
1937 ...
1938 __PACKAGE__->meta->setup
1939 (
1940 ...
1941 relationships =>
1942 [
1943 colors =>
1944 {
1945 type => 'many to many',
1946 map_class => 'ProductColorMap'
1947 map_from => 'product',
1948 map_to => 'color',
1949 },
1950 ...
1951 ],
1952 );
1953
1954 Note that only the map class needs to be "use"d in the "Product" class.
1955 The relationship definition specifies the name of the map class, and
1956 (optionally) the names of the foreign keys or "many to one"
1957 relationships in the map class that connect the two tables.
1958
1959 In most cases, these two parameters ("map_from" and "map_to") are
1960 unnecessary. Rose::DB::Object will figure out what to do given only
1961 the map class, so long as there's no ambiguity in the mapping table.
1962
1963 In this case, there is no ambiguity, so the relationship definition can
1964 be shortened to this.
1965
1966 use Product;
1967 ...
1968 __PACKAGE__->meta->setup
1969 (
1970 relationships =>
1971 [
1972 colors =>
1973 {
1974 type => 'many to many',
1975 map_class => 'ProductColorMap'
1976 },
1977 ],
1978 ...
1979 );
1980
1981 In fact, since the map table is named according to the default
1982 conventions, it can be shortened even further.
1983
1984 use Product;
1985 ...
1986 __PACKAGE__->meta->setup
1987 (
1988 relationships =>
1989 [
1990 colors => { type => 'many to many' },
1991 ...
1992 ],
1993 ...
1994 );
1995
1996 And further still:
1997
1998 use Product;
1999 ...
2000 __PACKAGE__->meta->setup
2001 (
2002 relationships =>
2003 [
2004 colors => 'many to many',
2005 ...
2006 ],
2007 ...
2008 );
2009
2010 (Classes can be shortened even more absurdly when auto-initialization
2011 is combined with the convention manager. See the convention manager
2012 documentation for an example.)
2013
2014 Now let's revisit the example code.
2015
2016 $p1 = Product->new(id => 10,
2017 name => 'Sled',
2018 colors =>
2019 [
2020 { name => 'red' },
2021 { name => 'green' }
2022 ]);
2023 $p1->save;
2024
2025 $p2 = Product->new(id => 20,
2026 name => 'Kite',
2027 colors =>
2028 [
2029 { name => 'blue' },
2030 { name => 'green' },
2031 { name => 'red' },
2032 ]);
2033 $p2->save;
2034
2035 The code works as expected, but the database now looks much nicer.
2036
2037 mydb=# select * from colors;
2038
2039 id | name
2040 ----+-------
2041 1 | red
2042 2 | green
2043 3 | blue
2044
2045
2046 mydb=# select * from product_color_map;
2047
2048 product_id | color_id
2049 ------------+----------
2050 10 | 1
2051 10 | 2
2052 20 | 3
2053 20 | 2
2054 20 | 1
2055
2056 Each color appears only once, and the mapping table handles all the
2057 connections between the "colors" and "products" tables.
2058
2059 The "many to many" "colors" method works much like the "one to many"
2060 "prices" method described earlier. The valid argument formats are the
2061 same.
2062
2063 • A list or reference to an array of objects of the appropriate
2064 class.
2065
2066 • A list or reference to an array of hash references containing
2067 name/value pairs used to construct such objects.
2068
2069 • A list or reference to an array of primary key values (but only if
2070 the foreign table has a single-column primary key).
2071
2072 The database modification behavior is also the same, with changes
2073 happening when the "parent" object is saved.
2074
2075 $p = Product->new(id => 123)->load;
2076
2077 $p->colors({ name => 'green' },
2078 { name => 'blue' });
2079
2080 $p->save; # database is modified here
2081
2082 Setting the list of colors replaces the old list, but in the case of a
2083 "many to many" relationship, only the map records are deleted.
2084
2085 $p = Product->new(id => 123)->load;
2086
2087 $p->colors({ name => 'pink' },
2088 { name => 'orange' });
2089
2090 # Delete old rows in the mapping table and create new ones
2091 $p->save;
2092
2093 New colors can be added without deleting and resetting the entire list:
2094
2095 # Add two colors to the existing list
2096 $p->add_colors({ name => 'gray' },
2097 { name => 'red' });
2098
2099 $p->save; # database is modified here
2100
2101 Passing a reference to an empty array will remove all colors associated
2102 with a particular product by deleting all the mapping table entries.
2103
2104 $p->colors([]);
2105 $p->save; # all mapping table entries for this product deleted here
2106
2107 Finally, the same caveats described earlier about deleting products
2108 that have associated prices apply to colors as well. Again, I
2109 recommend using a trigger in the database to handle this, but
2110 Rose::DB::Object's cascading delete feature will work in a pinch.
2111
2112 # Delete all associated rows in the prices table, plus any
2113 # rows in the product_color_map table, before deleting the
2114 # row in the products table.
2115 $p->delete(cascade => 1);
2116
2117 Relationship code summary
2118
2119 To summarize this exploration of inter-table relationships, here's a
2120 terse summary of the current state of our Perl classes, and the
2121 associated database tables.
2122
2123 For the sake of brevity, I've chosen to use the shorter versions of the
2124 foreign key and relationship definitions in the Perl classes shown
2125 below. Just remember that this only works when your tables, columns,
2126 and classes are named according to the expected conventions.
2127
2128 First, the database schema.
2129
2130 CREATE TABLE vendors
2131 (
2132 id SERIAL NOT NULL PRIMARY KEY,
2133 name VARCHAR(255) NOT NULL,
2134
2135 UNIQUE(name)
2136 );
2137
2138 CREATE TABLE products
2139 (
2140 id SERIAL NOT NULL PRIMARY KEY,
2141 name VARCHAR(255) NOT NULL,
2142
2143 vendor_id INT REFERENCES vendors (id),
2144
2145 status VARCHAR(128) NOT NULL DEFAULT 'inactive'
2146 CHECK(status IN ('inactive', 'active', 'defunct')),
2147
2148 date_created TIMESTAMP NOT NULL DEFAULT NOW(),
2149 release_date TIMESTAMP,
2150
2151 UNIQUE(name)
2152 );
2153
2154 CREATE TABLE prices
2155 (
2156 id SERIAL NOT NULL PRIMARY KEY,
2157 product_id INT NOT NULL REFERENCES products (id),
2158 region CHAR(2) NOT NULL DEFAULT 'US',
2159 price DECIMAL(10,2) NOT NULL DEFAULT 0.00,
2160
2161 UNIQUE(product_id, region)
2162 );
2163
2164 CREATE TABLE colors
2165 (
2166 id SERIAL NOT NULL PRIMARY KEY,
2167 name VARCHAR(255) NOT NULL,
2168
2169 UNIQUE(name)
2170 );
2171
2172 CREATE TABLE product_color_map
2173 (
2174 product_id INT NOT NULL REFERENCES products (id),
2175 color_id INT NOT NULL REFERENCES colors (id),
2176
2177 PRIMARY KEY(product_id, color_id)
2178 );
2179
2180 Now the Perl classes. Remember that these must each be in their own
2181 ".pm" files, despite appearing in one contiguous code snippet below.
2182
2183 package Vendor;
2184
2185 use base 'My::DB::Object';
2186
2187 __PACKAGE__->meta->setup
2188 (
2189 table => 'vendors',
2190 columns =>
2191 [
2192 id => { type => 'serial', primary_key => 1, not_null => 1 },
2193 name => { type => 'varchar', length => 255, not_null => 1 },
2194 ],
2195
2196 unique_key => 'name',
2197 );
2198
2199 1;
2200
2201
2202 package Product;
2203
2204 use base 'My::DB::Object';
2205
2206 __PACKAGE__->meta->setup
2207 (
2208 table => 'products',
2209 columns =>
2210 [
2211 id => { type => 'integer', not_null => 1 },
2212 name => { type => 'varchar', length => 255, not_null => 1 },
2213
2214 vendor_id => { type => 'int' },
2215 status => { type => 'varchar', default => 'inactive',
2216 length => 128, not_null => 1 },
2217 date_created => { type => 'timestamp', not_null => 1,
2218 default => 'now()' },
2219 release_date => { type => 'timestamp' },
2220 ]
2221
2222 primary_key_columns => 'id',
2223
2224 unique_key => 'name',
2225
2226 allow_inline_column_values => 1,
2227
2228 relationships =>
2229 [
2230 prices => 'one to many',
2231 colors => 'many to many',
2232 ]
2233 );
2234
2235 1;
2236
2237
2238 package Price;
2239
2240 use Product;
2241
2242 use base 'My::DB::Object';
2243
2244 __PACKAGE__->meta->setup
2245 (
2246 table => 'prices',
2247
2248 columns =>
2249 [
2250 id => { type => 'serial', primary_key => 1, not_null => 1 },
2251 product_id => { type => 'int', not_null => 1 },
2252 region => { type => 'char', length => 2, not_null => 1 },
2253 price =>
2254 {
2255 type => 'decimal',
2256 precision => 10,
2257 scale => 2,
2258 not_null => 1,
2259 default => 0.00
2260 },
2261 ],
2262
2263 unique_key => [ 'product_id', 'region' ],
2264
2265 foreign_key => [ 'product' ],
2266 );
2267
2268 1;
2269
2270
2271 package Color;
2272
2273 use base 'My::DB::Object';
2274
2275 __PACKAGE__->meta->setup
2276 (
2277 table => 'colors',
2278 columns =>
2279 [
2280 id => { type => 'serial', primary_key => 1, not_null => 1 },
2281 name => { type => 'varchar', length => 255, not_null => 1 },
2282 ],
2283 unique_key => 'name',
2284 );
2285
2286 1;
2287
2288
2289 package ProductColorMap;
2290
2291 use base 'My::DB::Object';
2292
2293 __PACKAGE__->meta->setup
2294 (
2295 table => 'product_color_map',
2296 columns =>
2297 [
2298 product_id => { type => 'int', not_null => 1 },
2299 color_id => { type => 'int', not_null => 1 },
2300 ],
2301 pk_columns => [ 'product_id', 'color_id' ],
2302 foreign_keys => [ 'product', 'color' ],
2303 );
2304
2305 1;
2306
2307 The loader
2308 If the code above still looks like too much work to you, try letting
2309 Rose::DB::Object::Loader do it all for you. Given the database schema
2310 shown above, the suite of associated Perl classes could have been
2311 created automatically with a single method call.
2312
2313 $loader =
2314 Rose::DB::Object::Loader->new(db => Rose::DB->new,
2315 class_prefix => 'My::');
2316
2317 $loader->make_classes;
2318
2319 If you want to see what the loader did for you, catch the return value
2320 of the make_classes method (which will be a list of class names) and
2321 then ask each class to print its perl equivalent.
2322
2323 @classes = $loader->make_classes;
2324
2325 foreach my $class (@classes)
2326 {
2327 if($class->isa('Rose::DB::Object'))
2328 {
2329 print $class->meta->perl_class_definition(braces => 'bsd',
2330 indent => 2), "\n";
2331 }
2332 else # Rose::DB::Object::Manager subclasses
2333 {
2334 print $class->perl_class_definition, "\n";
2335 }
2336 }
2337
2338 You can also ask the loader to make actual Perl modules (that is, a set
2339 of actual *.pm files in the file system) by calling the aptly named
2340 make_modules method.
2341
2342 The code created by the loader is shown below. Compare it to the
2343 manually created Perl code shown above and you'll see that it's nearly
2344 identical. Again, careful table name choices really help here. Do
2345 what the convention manager expects (or write your own convention
2346 manager subclass that does what you expect) and automation like this
2347 can work very well.
2348
2349 package My::Color;
2350
2351 use strict;
2352
2353 use base qw(My::DB::Object::Base1);
2354
2355 __PACKAGE__->meta->setup
2356 (
2357 table => 'colors',
2358
2359 columns =>
2360 [
2361 id => { type => 'integer', not_null => 1 },
2362 name => { type => 'varchar', length => 255, not_null => 1 },
2363 ],
2364
2365 primary_key_columns => [ 'id' ],
2366
2367 unique_keys => [ 'name' ],
2368
2369 relationships =>
2370 [
2371 products =>
2372 {
2373 column_map => { color_id => 'id' },
2374 foreign_class => 'My::Product',
2375 map_class => 'My::ProductColorMap',
2376 map_from => 'color',
2377 map_to => 'product',
2378 type => 'many to many',
2379 },
2380 ],
2381 );
2382
2383 1;
2384
2385 package My::Color::Manager;
2386
2387 use base qw(Rose::DB::Object::Manager);
2388
2389 use My::Color;
2390
2391 sub object_class { 'My::Color' }
2392
2393 __PACKAGE__->make_manager_methods('colors');
2394
2395 1;
2396
2397 package My::Price;
2398
2399 use strict;
2400
2401 use base qw(My::DB::Object::Base1);
2402
2403 __PACKAGE__->meta->setup
2404 (
2405 table => 'prices',
2406
2407 columns =>
2408 [
2409 id => { type => 'integer', not_null => 1 },
2410 product_id => { type => 'integer', not_null => 1 },
2411 region => { type => 'character', default => 'US', length => 2,
2412 not_null => 1 },
2413 price => { type => 'numeric', default => '0.00', not_null => 1,
2414 precision => 10, scale => 2 },
2415 ],
2416
2417 primary_key_columns => [ 'id' ],
2418
2419 unique_key => [ 'product_id', 'region' ],
2420
2421 foreign_keys =>
2422 [
2423 product =>
2424 {
2425 class => 'My::Product',
2426 key_columns =>
2427 {
2428 product_id => 'id',
2429 },
2430 },
2431 ],
2432 );
2433
2434 1;
2435
2436 package My::Price::Manager;
2437
2438 use base qw(Rose::DB::Object::Manager);
2439
2440 use My::Price;
2441
2442 sub object_class { 'My::Price' }
2443
2444 __PACKAGE__->make_manager_methods('prices');
2445
2446 1;
2447
2448 package My::ProductColorMap;
2449
2450 use strict;
2451
2452 use base qw(My::DB::Object::Base1);
2453
2454 __PACKAGE__->meta->setup
2455 (
2456 table => 'product_color_map',
2457
2458 columns =>
2459 [
2460 product_id => { type => 'integer', not_null => 1 },
2461 color_id => { type => 'integer', not_null => 1 },
2462 ],
2463
2464 primary_key_columns => [ 'product_id', 'color_id' ],
2465
2466 foreign_keys =>
2467 [
2468 color =>
2469 {
2470 class => 'My::Color',
2471 key_columns =>
2472 {
2473 color_id => 'id',
2474 },
2475 },
2476
2477 product =>
2478 {
2479 class => 'My::Product',
2480 key_columns =>
2481 {
2482 product_id => 'id',
2483 },
2484 },
2485 ],
2486 );
2487
2488 1;
2489
2490 package My::ProductColorMap::Manager;
2491
2492 use base qw(Rose::DB::Object::Manager);
2493
2494 use My::ProductColorMap;
2495
2496 sub object_class { 'My::ProductColorMap' }
2497
2498 __PACKAGE__->make_manager_methods('product_color_map');
2499
2500 1;
2501
2502 package My::ProductColor;
2503
2504 use strict;
2505
2506 use base qw(My::DB::Object::Base1);
2507
2508 __PACKAGE__->meta->setup
2509 (
2510 table => 'product_colors',
2511
2512 columns =>
2513 [
2514 id => { type => 'integer', not_null => 1 },
2515 product_id => { type => 'integer', not_null => 1 },
2516 color_code => { type => 'character', length => 3, not_null => 1 },
2517 ],
2518
2519 primary_key_columns => [ 'id' ],
2520 );
2521
2522 1;
2523
2524 package My::ProductColor::Manager;
2525
2526 use base qw(Rose::DB::Object::Manager);
2527
2528 use My::ProductColor;
2529
2530 sub object_class { 'My::ProductColor' }
2531
2532 __PACKAGE__->make_manager_methods('product_colors');
2533
2534 1;
2535
2536 package My::Product;
2537
2538 use strict;
2539
2540 use base qw(My::DB::Object::Base1);
2541
2542 __PACKAGE__->meta->setup
2543 (
2544 table => 'products',
2545
2546 columns =>
2547 [
2548 id => { type => 'integer', not_null => 1 },
2549 name => { type => 'varchar', length => 255, not_null => 1 },
2550 price => { type => 'numeric', default => '0.00', not_null => 1,
2551 precision => 10, scale => 2 },
2552 vendor_id => { type => 'integer' },
2553 status => { type => 'varchar', default => 'inactive',
2554 length => 128, not_null => 1 },
2555 date_created => { type => 'timestamp', default => 'now()',
2556 not_null => 1 },
2557 release_date => { type => 'timestamp' },
2558 ],
2559
2560 primary_key_columns => [ 'id' ],
2561
2562 unique_keys => [ 'name' ],
2563
2564 allow_inline_column_values => 1,
2565
2566 foreign_keys =>
2567 [
2568 vendor =>
2569 {
2570 class => 'My::Vendor',
2571 key_columns =>
2572 {
2573 vendor_id => 'id',
2574 },
2575 },
2576 ],
2577
2578 relationships =>
2579 [
2580 colors =>
2581 {
2582 column_map => { product_id => 'id' },
2583 foreign_class => 'My::Color',
2584 map_class => 'My::ProductColorMap',
2585 map_from => 'product',
2586 map_to => 'color',
2587 type => 'many to many',
2588 },
2589
2590 prices =>
2591 {
2592 class => 'My::Price',
2593 key_columns => { id => 'product_id' },
2594 type => 'one to many',
2595 },
2596 ],
2597 );
2598
2599 1;
2600
2601 package My::Product::Manager;
2602
2603 use base qw(Rose::DB::Object::Manager);
2604
2605 use My::Product;
2606
2607 sub object_class { 'My::Product' }
2608
2609 __PACKAGE__->make_manager_methods('products');
2610
2611 1;
2612
2613 package My::Vendor;
2614
2615 use strict;
2616
2617 use base qw(My::DB::Object::Base1);
2618
2619 __PACKAGE__->meta->setup
2620 (
2621 table => 'vendors',
2622
2623 columns =>
2624 [
2625 id => { type => 'integer', not_null => 1 },
2626 name => { type => 'varchar', length => 255, not_null => 1 },
2627 ],
2628
2629 primary_key_columns => [ 'id' ],
2630
2631 unique_keys => [ 'name' ],
2632
2633 relationships =>
2634 [
2635 products =>
2636 {
2637 class => 'My::Product',
2638 key_columns => { id => 'vendor_id' },
2639 type => 'one to many',
2640 },
2641 ],
2642 );
2643
2644 1;
2645
2646 package My::Vendor::Manager;
2647
2648 use base qw(Rose::DB::Object::Manager);
2649
2650 use My::Vendor;
2651
2652 sub object_class { 'My::Vendor' }
2653
2654 __PACKAGE__->make_manager_methods('vendors');
2655
2656 1;
2657
2658 Auto-joins and other Manager features
2659 The "Product::Manager" class we created earlier is deceptively simple.
2660 Setting it up can actually be reduced to a one-liner, but it provides a
2661 rich set of features.
2662
2663 The basics demonstrated earlier cover most kinds of single-table SELECT
2664 statements. But as the "Product" class has become more complex,
2665 linking to other objects via foreign keys and other relationships,
2666 selecting rows from just the "products" table has become a lot less
2667 appealing. What good is it to retrieve hundreds of products in a
2668 single query when you then have to execute hundreds of individual
2669 queries to get the prices of those products?
2670
2671 This is what SQL JOINs were made for: selecting related rows from
2672 multiple tables simultaneously. Rose::DB::Object::Manager supports a
2673 two kinds of joins. The interface to this functionality is presented
2674 in terms of objects via the "require_objects" and "with_objects"
2675 parameters to the get_objects() method.
2676
2677 Both parameters expect a list of foreign key or relationship names.
2678 The "require_objects" parameters will use an "inner join" to fetch
2679 related objects, while the "with_objects" parameter will perform an
2680 "outer join."
2681
2682 If you're unfamiliar with these terms, it's probably a good idea to
2683 learn about them from a good SQL book or web tutorial. But even if
2684 you've never written an SQL JOIN by hand, there's not much you need to
2685 understand in order to use your manager class effectively.
2686
2687 The rule of thumb is simple. When you want each and every object
2688 returned by your query to have a particular related object, then use
2689 the "require_objects" parameter. But if you do not want to exclude
2690 objects even if they do not have a particular related object attached
2691 to them yet, then use the "with_objects" parameter.
2692
2693 Sometimes, this decision is already made for you by the table
2694 structure. For example, let's modify the "products" table in order to
2695 require that every single product has a vendor. To do so, we'll change
2696 the "vendor_id" column definition from this:
2697
2698 vendor_id INT REFERENCES vendors (id)
2699
2700 to this:
2701
2702 vendor_id INT NOT NULL REFERENCES vendors (id)
2703
2704 Now it's impossible for a product to have a NULL "vendor_id". And
2705 since our database enforces referential integrity, it's also impossible
2706 for the "vendor_id" column to have a value that does not refer to the
2707 "id" of an existing row in the "vendors" table.
2708
2709 While the "with_objects" parameter could technically be used to fetch
2710 "Product"s with their associated "Vendor" objects, it would be
2711 wasteful. (Outer joins are often less efficient than inner joins.)
2712 The table structure basically dictates that the "require_objects"
2713 parameter be used when fetching "Product"s with their "Vendor"s.
2714
2715 Here's how such a query could actually look.
2716
2717 $products =
2718 Product::Manager->get_products(
2719 query =>
2720 [
2721 name => { like => 'Kite%' },
2722 id => { gt => 15 },
2723 ]
2724 require_objects => [ 'vendor' ],
2725 sort_by => 'name');
2726
2727 Recall that the name of the foreign key that connects a product to its
2728 vendor is "vendor". Thus, the value of the "require_objects" parameter
2729 is a reference to an array containing this name.
2730
2731 Getting information about each product's vendor now no longer requires
2732 additional database queries.
2733
2734 foreach my $product (@$products)
2735 {
2736 # This does not hit the database at all
2737 print $product->vendor->name, "\n";
2738 }
2739
2740 For the SQL-inclined, the actual query run looks something like this.
2741
2742 SELECT
2743 t1.date_created,
2744 t1.id,
2745 t1.name,
2746 t1.release_date,
2747 t1.status,
2748 t1.vendor_id,
2749 t2.id,
2750 t2.name
2751 FROM
2752 products t1,
2753 vendors t2
2754 WHERE
2755 t1.id >= 16 AND
2756 t1.name LIKE 'Kite%' AND
2757 t1.vendor_id = t2.id
2758 ORDER BY t1.name
2759
2760 As you can see, the query includes "tN" aliases for each table. This
2761 is important because columns in separate tables often have identical
2762 names. For example, both the "products" and the "vendors" tables have
2763 columns named "id" and "name".
2764
2765 In the query, you'll notice that the "name => { like => 'Kite%' }"
2766 argument ended up filtering on the product name rather than the vendor
2767 name. This is intentional. Any unqualified column name that is
2768 ambiguous is considered to belong to the "primary" table ("products",
2769 in this case).
2770
2771 The "tN" numbering is deterministic. The primary table is always "t1",
2772 and secondary tables are assigned ascending numbers starting from
2773 there. You can find a full explanation of the numbering rules in the
2774 Rose::DB::Object::Manager documentation.
2775
2776 In the example above, if we wanted to filter and sort on the vendor
2777 name instead, we could do this.
2778
2779 $products =
2780 Product::Manager->get_products(
2781 query =>
2782 [
2783 't2.name' => { like => 'Acm%' },
2784 id => { gt => 15 },
2785 ]
2786 require_objects => [ 'vendor' ],
2787 sort_by => 't2.name');
2788
2789 But that's not the only option. There are several ways to disambiguate
2790 a query clause. The column name can also be qualified by prefixing it
2791 with a relationship name.
2792
2793 $products =
2794 Product::Manager->get_products(
2795 query =>
2796 [
2797 'vendor.name' => { like => 'Acm%' },
2798 id => { gt => 15 },
2799 ]
2800 require_objects => [ 'vendor' ],
2801 sort_by => 'vendor.name');
2802
2803 The actual table name itself can also be used (although I do not
2804 recommend this practice since you will have to change all such usage
2805 instances if you ever rename the table).
2806
2807 $products =
2808 Product::Manager->get_products(
2809 query =>
2810 [
2811 'vendors.name' => { like => 'Acm%' },
2812 id => { gt => 15 },
2813 ]
2814 require_objects => [ 'vendor' ],
2815 sort_by => 'vendors.name');
2816
2817 Now let's see an example of the "with_objects" parameter in action.
2818 Each "Product" has zero or more "Price"s. Let's fetch products with
2819 all their associated prices. And remember that some of these products
2820 may have no prices at all.
2821
2822 $products =
2823 Product::Manager->get_products(
2824 query =>
2825 [
2826 name => { like => 'Kite%' },
2827 id => { gt => 15 },
2828 ],
2829 with_objects => [ 'prices' ],
2830 sort_by => 'name');
2831
2832 Again, since the name of the "one to many" relationship that connects a
2833 product to its prices is "prices", this is the value use in the
2834 "with_objects" parameter. The SQL looks something like this:
2835
2836 SELECT
2837 t1.date_created,
2838 t1.id,
2839 t1.name,
2840 t1.release_date,
2841 t1.status,
2842 t1.vendor_id,
2843 t2.id,
2844 t2.price,
2845 t2.product_id,
2846 t2.region
2847 FROM
2848 products t1
2849 LEFT OUTER JOIN prices t2 ON(t1.id = t2.product_id)
2850 WHERE
2851 t1.id > 15 AND
2852 t1.name LIKE 'Kite%'
2853 ORDER BY t1.name
2854
2855 Fetching products with both their vendors and prices (if any) is
2856 straightforward. Just use the "require_objects" parameter for the
2857 vendors and the "with_objects" parameter for the prices.
2858
2859 $products =
2860 Product::Manager->get_products(
2861 query =>
2862 [
2863 name => { like => 'Kite%' },
2864 id => { gt => 15 },
2865 ],
2866 require_objects => [ 'vendor' ],
2867 with_objects => [ 'prices' ],
2868 sort_by => 'name');
2869
2870 The resulting SQL is what you'd expect.
2871
2872 SELECT
2873 t1.date_created,
2874 t1.id,
2875 t1.name,
2876 t1.release_date,
2877 t1.status,
2878 t1.vendor_id,
2879 t2.id,
2880 t2.price,
2881 t2.product_id,
2882 t2.region,
2883 t3.id,
2884 t3.name
2885 FROM
2886 products t1
2887 JOIN vendors t3 ON (t1.vendor_id = t3.id)
2888 LEFT OUTER JOIN prices t2 ON(t1.id = t2.product_id)
2889 WHERE
2890 t1.id > 15 AND
2891 t1.name LIKE 'Kite%'
2892 ORDER BY t1.name
2893
2894 Each "Product" also has zero or more "Color"s which are related to it
2895 through a mapping table (fronted by the "ProductColorMap" class, but we
2896 don't need to know that). The "with_objects" parameter can handle that
2897 as well.
2898
2899 $products =
2900 Product::Manager->get_products(
2901 query =>
2902 [
2903 name => { like => 'Kite%' },
2904 id => { gt => 15 },
2905 ],
2906 with_objects => [ 'colors' ],
2907 sort_by => 'name');
2908
2909 The resulting SQL is a bit more complex.
2910
2911 SELECT
2912 t1.date_created,
2913 t1.id,
2914 t1.name,
2915 t1.release_date,
2916 t1.status,
2917 t1.vendor_id,
2918 t3.id,
2919 t3.name
2920 FROM
2921 products t1
2922 LEFT OUTER JOIN product_color_map t2 ON(t2.product_id = t1.id)
2923 LEFT OUTER JOIN colors t3 ON(t2.color_id = t3.id)
2924 WHERE
2925 t1.id > 15 AND
2926 t1.name LIKE 'Kite%'
2927
2928 Again, combinations are straightforward. Let's fetch products with
2929 their vendors and colors.
2930
2931 $products =
2932 Product::Manager->get_products(
2933 query =>
2934 [
2935 name => { like => 'Kite%' },
2936 id => { gt => 15 },
2937 ],
2938 require_objects => [ 'vendor' ],
2939 with_objects => [ 'colors' ],
2940 sort_by => 'name');
2941
2942 Now the SQL is starting to get a bit hairy.
2943
2944 SELECT
2945 t1.id,
2946 t1.name,
2947 t1.vendor_id,
2948 t3.code,
2949 t3.name,
2950 t4.id,
2951 t4.name,
2952 t4.region_id
2953 FROM
2954 products t1
2955 JOIN vendors t4 ON (t1.vendor_id = t4.id)
2956 LEFT OUTER JOIN product_colors t2 ON (t2.product_id = t1.id)
2957 LEFT OUTER JOIN colors t3 ON (t2.color_code = t3.code)
2958 WHERE
2959 t1.id > 15 AND
2960 t1.name LIKE 'Kite%'
2961
2962 Anyone who knows SQL well will recognize that there is a danger lurking
2963 when combining JOINs. Multiple joins that each fetch multiple rows can
2964 result in a geometric explosion of rows returned by the database. For
2965 example, the number of rows returned when fetching products with their
2966 associated prices and colors would be:
2967
2968 <number of matching products> x
2969 <number of prices for each product> x
2970 <number of colors for each product>
2971
2972 That number can get very large, very fast if products have many prices,
2973 colors, or both. (The last two terms in the multiplication maybe
2974 switched, depending on the order of the actual JOIN clauses, but the
2975 results are similar.) And the problem only gets worse as the number of
2976 objects related by "... to many" relationships increases.
2977
2978 That said, Rose::DB::Object::Manager does allow multiple objects
2979 related by "... to many" relationships to be fetched simultaneously.
2980 But it requires the developer to supply the "multi_many_ok" parameter
2981 with a true value as a form of confirmation. "Yes, I know the risks,
2982 but I want to do it anyway."
2983
2984 As an example, let's try fetching products with their associated
2985 prices, colors, and vendors. To do so, we'll have to include the
2986 "multi_many_ok" parameter.
2987
2988 $products =
2989 Product::Manager->get_products(
2990 query =>
2991 [
2992 name => { like => 'Kite%' },
2993 id => { gt => 15 },
2994 ],
2995 require_objects => [ 'vendor' ],
2996 with_objects => [ 'colors', 'prices' ],
2997 multi_many_ok => 1,
2998 sort_by => 'name');
2999
3000 Here's the SQL.
3001
3002 SELECT
3003 t1.id,
3004 t1.name,
3005 t1.vendor_id,
3006 t3.code,
3007 t3.name,
3008 t4.price_id,
3009 t4.product_id,
3010 t4.region,
3011 t4.price,
3012 t5.id,
3013 t5.name,
3014 t5.region_id
3015 FROM
3016 products t1
3017 JOIN vendors t5 ON (t1.vendor_id = t5.id)
3018 LEFT OUTER JOIN product_colors t2 ON (t2.product_id = t1.id)
3019 LEFT OUTER JOIN colors t3 ON (t2.color_code = t3.code)
3020 LEFT OUTER JOIN prices t4 ON (t1.id = t4.product_id)
3021 WHERE
3022 t1.id > 15 AND
3023 t1.name LIKE 'Kite%'
3024 ORDER BY t1.name
3025
3026 It's questionable whether this five-way join will be faster than doing
3027 a four- or three-way join and then fetching the other information after
3028 the fact, with separate queries. It all depends on the number of rows
3029 expected to match. Only you know your data. You must choose the most
3030 efficient query that suits your needs.
3031
3032 Moving beyond even the example above, it's possible to chain foreign
3033 key or relationship names to an arbitrary depth. For example, imagine
3034 that each "Vendor" has a "Region" related to it by a foreign key named
3035 "region". The following call will get region information for each
3036 product's vendor, filtering on the region name.
3037
3038 $products =
3039 Product::Manager->get_products(
3040 query =>
3041 [
3042 'vendor.region.name' => 'UK',
3043 'name' => { like => 'Kite%' },
3044 'id' => { gt => 15 },
3045 ],
3046 require_objects => [ 'vendor.region' ],
3047 with_objects => [ 'colors', 'prices' ],
3048 multi_many_ok => 1,
3049 sort_by => 'name');
3050
3051 The SQL would now look something like this.
3052
3053 SELECT
3054 t1.id,
3055 t1.name,
3056 t1.vendor_id,
3057 t3.code,
3058 t3.name,
3059 t4.price_id,
3060 t4.product_id,
3061 t4.region,
3062 t4.price,
3063 t5.id,
3064 t5.name,
3065 t5.region_id,
3066 t6.id,
3067 t6.name
3068 FROM
3069 products t1
3070 JOIN (vendors t5 JOIN regions t6 ON (t5.region_id = t6.id))
3071 ON (t1.vendor_id = t5.id)
3072 LEFT OUTER JOIN product_colors t2 ON (t2.product_id = t1.id)
3073 LEFT OUTER JOIN colors t3 ON (t2.color_code = t3.code)
3074 LEFT OUTER JOIN prices t4 ON (t1.id = t4.product_id)
3075 WHERE
3076 t1.id > 15 AND
3077 t1.name LIKE 'Kite%' AND
3078 t6.name = 'UK'
3079 ORDER BY t1.name
3080
3081 The same caveat about performance and the potential explosion of
3082 redundant data when JOINing across multiple "... to many" relationships
3083 also applies to the "chained" selectors demonstrated above--even more
3084 so, in fact, as the depth of the chain increases. That said, it's
3085 usually safe to go a few levels deep into "... to one" relationships
3086 when using the "require_objects" parameter.
3087
3088 Finally, it's also possible to load a single product with all of its
3089 associated foreign objects. The load() method accepts a "with"
3090 parameter that takes a list of foreign key and relationship names.
3091
3092 $product = Product->new(id => 1234);
3093 $product->load(with => [ 'vendor', 'colors', 'prices' ]);
3094
3095 The same "multi many" caveats apply, but the "multi_many_ok" parameter
3096 is not required in this case. The assumption is that a single object
3097 won't have too many related objects. But again, only you know your
3098 data, so be careful.
3099
3100 Wrap-up
3101 I hope you've learned something from this tutorial. Although it is by
3102 no means a complete tour of all of the features of Rose::DB::Object, it
3103 does hit most of the highlights. This tutorial will likely expand in
3104 the future, and a separate document describing the various ways that
3105 Rose::DB::Object can be extended is also planned. For now, there is a
3106 brief overview that was pulled from the Rose::DB::Object mailing list
3107 in the wiki.
3108
3109 https://github.com/siracusa/rose/wiki/Extending-Rose%3A%3ADB%3A%3AObject
3110
3111 See the support section below for more information on the mailing list.
3112
3114 The Rose development policy applies to this, and all "Rose::*" modules.
3115 Please install Rose from CPAN and then run ""perldoc Rose"" for more
3116 information.
3117
3119 Any Rose::DB::Object questions or problems can be posted to the
3120 Rose::DB::Object mailing list. To subscribe to the list or view the
3121 archives, go here:
3122
3123 <http://groups.google.com/group/rose-db-object>
3124
3125 Although the mailing list is the preferred support mechanism, you can
3126 also email the author (see below) or file bugs using the CPAN bug
3127 tracking system:
3128
3129 <http://rt.cpan.org/NoAuth/Bugs.html?Dist=Rose-DB-Object>
3130
3131 There's also a wiki and other resources linked from the Rose project
3132 home page:
3133
3134 <http://rosecode.org>
3135
3137 John C. Siracusa (siracusa@gmail.com)
3138
3140 Copyright (c) 2007 by John C. Siracusa. All rights reserved. This
3141 program is free software; you can redistribute it and/or modify it
3142 under the same terms as Perl itself.
3143
3144
3145
3146perl v5.38.0 2023-07-21 Rose::DB::Object::Tutorial(3)