Description :
the Rose::DB::Object manpage is a base class for objects that encapsulate a single row in a database table. the Rose::DB::Object manpage-derived objects are sometimes simply called \"the Rose::DB::Object manpage objects\" in this documentation for the sake of brevity, but be assured that derivation is the only reasonable way to use this class.
the Rose::DB::Object manpage inherits from, and follows the conventions of, the Rose::Object manpage. See the the Rose::Object manpage documentation for more information.
For an informal overview of this module distribution, consult the the Rose::DB::Object::Tutorial manpage.
Restrictions the Rose::DB::Object manpage objects can represent rows in almost any database table, subject to the following constraints.
* * The database server must be supported by the Rose::DB manpage.
* * The database table must have a primary key.
* * The primary key must not allow null values in any of its columns.
Although the list above contains the only hard and fast rules, there may be other realities that you\'ll need to work around.
The most common example is the existence of a column name in the database table that conflicts with the name of a method in the the Rose::DB::Object manpage API. There are two possible workarounds: either explicitly alias the column, or define a Rose::DB::Object::Metadata/column_name_to_method_name_mapper. See the Rose::DB::Object::Metadata/alias_column and Rose::DB::Object::Metadata/column_name_to_method_name_mapper methods in the the Rose::DB::Object::Metadata manpage documentation for more details.
There are also varying degrees of support for data types in each database server supported by the Rose::DB manpage. If you have a table that uses a data type not supported by an existing the Rose::DB::Object::Metadata::Column manpage-derived class, you will have to write your own column class and then map it to a type name using the Rose::DB::Object::Metadata manpage\'s Rose::DB::Object::Metadata/column_type_class method, yada yada. (Or, of course, you can map the new type to an existing column class.)
The entire framework is extensible. This module distribution contains straight-forward implementations of the most common column types, but there\'s certainly more that can be done. Submissions are welcome.
Features the Rose::DB::Object manpage provides the following functions:
* * Create a row in the database by saving a newly constructed object.
* * Initialize an object by loading a row from the database.
* * Update a row by saving a modified object back to the database.
* * Delete a row from the database.
* * Fetch an object referred to by a foreign key in the current object. (i.e., \"one to one\" and \"many to one\" relationships.)
* * Fetch multiple objects that refer to the current object, either directly through foreign keys or indirectly through a mapping table. (i.e., \"one to many\" and \"many to many\" relationships.)
* * Load an object along with \"foreign objects\" that are related through any of the supported relationship types.
Objects can be loaded based on either a primary key or a unique key. Since all tables fronted by the Rose::DB::Object manpages must have non-null primary keys, insert, update, and delete operations are done based on the primary key.
In addition, its sibling class, the Rose::DB::Object::Manager manpage, can do the following:
* * Fetch multiple objects from the database using arbitrary query conditions, limits, and offsets.
* * Iterate over a list of objects, fetching from the database in response to each step of the iterator.
* * Fetch objects along with \"foreign objects\" (related through any of the supported relationship types) in a single query by automatically generating the appropriate SQL join(s).
* * Count the number of objects that match a complex query.
* * Update objects that match a complex query.
* * Delete objects that match a complex query.
the Rose::DB::Object::Manager manpage can be subclassed and used separately (the recommended approach), or it can create object manager methods within a the Rose::DB::Object manpage subclass. See the the Rose::DB::Object::Manager manpage documentation for more information.
the Rose::DB::Object manpage can parse, coerce, inflate, and deflate column values on your behalf, providing the most convenient possible data representations on the Perl side of the fence, while allowing the programmer to completely forget about the ugly details of the data formats required by the database. Default implementations are included for most common column types, and the framework is completely extensible.
Finally, the the Rose::DB::Object::Loader manpage can be used to automatically create a suite of the Rose::DB::Object manpage and the Rose::DB::Object::Manager manpage subclasses based on the contents of the database.
Configuration Before the Rose::DB::Object manpage can do any useful work, you must register at least one the Rose::DB manpage data source. By default, the Rose::DB::Object manpage instantiates a the Rose::DB manpage object by passing no arguments to its constructor. (See the /db method.) If you register a the Rose::DB manpage data source using the default type and domain, this will work fine. Otherwise, you must override the /meta method in your the Rose::DB::Object manpage subclass and have it return the appropriate the Rose::DB manpage-derived object.
To define your own the Rose::DB::Object manpage-derived class, you must describe the table that your class will act as a front-end for. This is done through the the Rose::DB::Object::Metadata manpage object associated with each the Rose::DB::Object manpage-dervied class. The metadata object is accessible via the Rose::DB::Object manpage\'s /meta method.
Metadata objects can be populated manually or automatically. Both techniques are shown in the /SYNOPSIS above. The automatic mode works by asking the database itself for the information. There are some caveats to this approach. See the Rose::DB::Object::Metadata/\"AUTO-INITIALIZATION\" section of the the Rose::DB::Object::Metadata manpage documentation for more information.
Serial and Auto-Incremented Columns Most databases provide a way to use a series of arbitrary integers as primary key column values. Some support a native \'SERIAL\' column data type. Others use a special auto-increment column attribute.
the Rose::DB::Object manpage supports at least one such serial or auto-incremented column type in each supported database. In all cases, the the Rose::DB::Object manpage-derived class setup is the same:
package My::DB::Object; ... __PACKAGE__->meta->setup ( columns => [ id => { type => \'serial\', primary_key => 1, not_null => 1 }, ... ], ... );
(Note that the column doesn\'t have to be named \"id\"; it can be named anything.)
If the database column uses big integers, use \"Rose::DB::Object::Metadata::Column::BigSerial\" column \'type\' instead.
Given the column metadata definition above, the Rose::DB::Object manpage will automatically generate and/or retrieve the primary key column value when an object is /saved. Example:
$o = My::DB::Object->new(name => \'bud\'); # no id specified $o->save; # new id value generated here
print \"Generated new id value: \", $o->id;
This will only work, however, if the corresponding column definition in the database is set up correctly. The exact technique varies from vendor to vendor. Below are examples of primary key column definitions that provide auto-generated values. There\'s one example for each of the databases supported by the Rose::DB manpage.
* * PostgreSQL
CREATE TABLE mytable ( id SERIAL PRIMARY KEY, ... );
* * MySQL
CREATE TABLE mytable ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, ... );
* * SQLite
CREATE TABLE mytable ( id INTEGER PRIMARY KEY AUTOINCREMENT, ... );
* * Informix
CREATE TABLE mytable ( id SERIAL NOT NULL PRIMARY KEY, ... );
* * Oracle
Since Oracle does not natively support a serial or auto-incremented column data type, an explicit sequence and trigger must be created to simulate the behavior. The sequence should be named according to this convention: \'< table>_< column>_seq\'. For example, if the table is named \'mytable\' and the column is named \'id\', then the sequence should be named \'mytable_id_seq\'. Here\'s an example database setup.
CREATE TABLE mytable ( id INT NOT NULL PRIMARY KEY, ... );
CREATE SEQUENCE mytable_id_seq;
CREATE TRIGGER mytable_insert BEFORE INSERT ON mytable FOR EACH ROW BEGIN SELECT NVL(:new.id, mytable_id_seq.nextval) INTO :new.id FROM dual; END;
Note the use of \'NVL()\' in the trigger, which allows the value of the \'id\' column to be set explicitly. If a non-NULL value for the \'id\' column is provided, then a new value is not pulled from the sequence.
If the sequence is not named according to the \'< table>_< column>_seq\' convention, you can specify the sequence name explicitly in the column metadata. Example:
columns => [ id => { type => \'serial\', primary_key => 1, not_null => 1, sequence => \'some_other_seq\' }, ...
If the table has a multi-column primary key or does not use a column type that supports auto-generated values, you can define a custom primary key generator function using the Rose::DB::Object::Metadata/primary_key_generator method of the the Rose::DB::Object::Metadata manpage-derived object that contains the metadata for this class. Example:
package MyDBObject;
use base qw(Rose::DB::Object);
__PACKAGE__->meta->setup ( table => \'mytable\',
columns => [ k1 => { type => \'int\', not_null => 1 }, k2 => { type => \'int\', not_null => 1 }, name => { type => \'varchar\', length => 255 }, ... ],
primary_key_columns => [ \'k1\', \'k2\' ],
primary_key_generator => sub { my($meta, $db) = AATT_;
my $k1 = ...; my $k2 = ...;
return $k1, $k2; }, );
See the the Rose::DB::Object::Metadata manpage documentation for more information on custom primary key generators.
Inheritance Simple, single inheritance between the Rose::DB::Object manpage-derived classes is supported. (Multiple inheritance is not currently supported.) The first time the /meta for a given class is accessed, it is created by making a one-time \"deep copy\" of the base class\'s metadata object (as long that the base class has one or more Rose::DB::Object::Metadata/columns set). This includes all columns, relationships, foreign keys, and other metadata from the base class. From that point on, the subclass may add to or modify its metadata without affecting any other class.
*Tip:* When using perl 5.8.0 or later, the the Scalar::Util::Clone manpage module is highly recommended. If it\'s installed, it will be used to more efficiently clone base-class metadata objects.
If the base class has already been Rose::DB::Object::Metadata/initialize, the subclass must explicitly specify whether it wants to create a new set of column and relationship methods, or merely inherit the methods from the base class. If the subclass contains any metadata modifications that affect method creation, then it must create a new set of methods to reflect those changes.
Finally, note that column types cannot be changed \"in-place.\" To change a column type, delete the old column and add a new one with the same name. This can be done in one step with the Rose::DB::Object::Metadata/replace_column method.
Example:
package BaseClass; use base \'Rose::DB::Object\';
__PACKAGE__->meta->setup ( table => \'objects\',
columns => [ id => { type => \'int\', primary_key => 1 }, start => { type => \'scalar\' }, ], );
...
package SubClass; use base \'BaseClass\';
__PACKAGE__->meta->column(\'id\')->default(123);
__PACKAGE__->meta->replace_column(start => { type => \'datetime\' });
__PACKAGE__->meta->initialize(replace_existing => 1);
...
$b = BaseClass->new;
$id = $b->id; # undef
$b->start(\'1/2/2003\'); print $b->start; # \'1/2/2003\' (plain string)
$s = SubClass->new;
$id = $s->id; # 123
$b->start(\'1/2/2003\'); # Value is converted to a DateTime object print $b->start->strftime(\'%B\'); # \'January\'
To preserve all inherited methods in a subclass, do this instead:
package SubClass; use base \'BaseClass\'; __PACKAGE__->meta->initialize(preserve_existing => 1);
Error Handling Error handling for the Rose::DB::Object manpage-derived objects is controlled by the Rose::DB::Object::Metadata/error_mode method of the the Rose::DB::Object::Metadata manpage object associated with the class (accessible via the /meta method). The default setting is \"fatal\", which means that the Rose::DB::Object manpage methods will Carp/croak if they encounter an error.
*PLEASE NOTE:* The error return values described in the /\"OBJECT METHODS\" documentation are only relevant when the error mode is set to something \"non-fatal.\" In other words, if an error occurs, you\'ll never see any of those return values if the selected error mode perlfunc/dies or Carp/croaks or otherwise throws an exception when an error occurs.
|