Class::Persist - Persistency framework for objects
package My::Person; use base qw( Class::Persist ); __PACKAGE__->dbh( $dbh ); __PACKAGE__->simple_db_spec( first_name => 'CHAR(30)', last_name => 'CHAR(30)', address => "My::Address", # has_a relationship phones => [ "My::Phone" ], # has_many relationship ); my $person = My::Person->new( first_name => "Dave" ); $person->addesss( My::Address->new ); $person->store;
Provides the framework to persist the objects in a DB in a Class::DBI style
A string representing when this object was originally created.
Loads an object from the database. Can be used in three different ways -
loads an object based on its oid
get the first match of single key test
Person->load( name => "Dave" );
loads an object based on its current state, eg -
my $person = Person->new; $person->name('Harry'); $person->load or die "There's noone called Harry"; print $person->email;
revert an object back to its state in the database.
TODO - make recursive
Store the object in DB and all objects within, whether it is a new object or an update
Deletes the object and returns true if successful. It will delete recursively all objects within.
Deletes the object and returns true if successful. Does not delete recursively any objects within.
Store the class and oid to make future retrieval easier
Stores the object in the deleted object table.
Stores all objects in a might-have relationship with this class.
Stores all objects in a one-to-many relationship with this class.
Store the object, and replace an object with a Class::Persist::Proxy pointing at it in the database.
Replace oids by a proxy
Deep-clones the object - any child objects will also be cloned. All new objects will have new oids.
Returns true if the object is in a good, consistent state and can be stored. Override this method if you want to make sure your objects are consistent before storing.
Returns true if the current object is unique, ie there is no other row in the database that has the same value as this object. The query that is used to check for uniqueness is defined by the unique_params method.
Only checked for unstored objects - objects that have come from the database are presumed to be unique.
Compares all the fields containing a scalar except oid
Class method. Defines a has_a relationship with another class.
Person::Body->has_a( head => "Person::Head" ); my $nose = $body->head->nose;
Allows you to store references to other Class::Persist objects. They will be serialised when stored in the database.
Class method. Defineds a one to many relationship with another class.
Person::Body->has_many( arms => 'Person::Arm' ); my $number_of_arms = $body->arms->count;
Allows you to manipulate a number of other Class::Persist objects that are associated with this one. This method will return a Class::Persist::Proxy::Container that handles the child objects, it provides push, pop, count, etc, methods to add and remove objects from the list.
my $left_arm = Person::Arm->new; $body->arms->push( $left_arm );
SQL query and binding params used to check unicity of object in DB
Get/set accessor for the DB table used to store this class.
Get/set accessor for the DB fields used to store the attributes specific to class (but not its parent(s)). Override this in your class to define the scalar properties of your object that should be stored in columns of the database.
Get/set accessor for all the DB fields used to store this class.
Insert the object in the DB as a new entry
Update the object in the DB
Generate SQL for an insert statement for this object
Generate SQL for an update statement for this object
SQL to specificy the database columns needed to store the attributes of this class - all parent class(es) columns are aggregated and used to build an SQL create table statement. Override this to specify the columns used by your class, if you want Class::Persist to be able to create your table for you. Remember to call the superclass db_fields_spec as well, though.
sub db_fields_spec( shift->SUPER::db_fields_spec, 'Colour VARCHAR(63)', 'Mass VARCHAR(63)', );
An alternative way of specifying the database spec, combining the field list, has_a and has_many relationships and the database spec in one command.
Person::Foot->simple_db_spec( digits => 'INT', name => 'CHAR(10)', leg => 'Person::Leg', hairs => [ 'Person::Leg::Hair' ], );
For each colnm as the keys of the passed hash, specify a simple DB field with a DB type, a has_a relationship with a class name, and a has_many relationship with a listref continain a single element - the class name.
This will also automatically create a name for the database table, if you don't want to supply one yourself. The name will be based on the package name.
Drop the table for this class.
Create the table for this class.
Class::Persist needs the existence of 2 tables in addition to the ones used to store object data. This method will create the tables in the database for this object.
Class::Persist needs the existence of 2 tables in addition to the ones used to store object data. This method will remove the tables from the database for this object.
Returns a list of all the objects in this classes table in the database.
Takes a hash of attribute=>value pairs. Values of undef become IS NULL tests. Returns a list of objects in the database of this class which match these criteria.
my $pears = Fruit->search( shape => 'pear' );
The special parameter 'order_by' will not be used as part of the search, but will order the results by that column.
my $sorted_pears = Fruit->search( shape => 'pear', order_by => 'size' );
Free-form search based on a SQL query. Returns a list of objects from the database for each row of the passed SQL 'WHERE' clause. You can use placeholders in this string, passing the values for the placeholders as the 2nd, etc, params
Person->sql("name LIKE '%ob%' AND age > ? ORDER BY height", $min_age)
when search() isn't good enough, and even sql() isn't good enough, you want advanced_search. You pass a complete SQL statement that will return a number of rows. It is assumed that the left-most column will contain oids. These oids will be inflated from the database and returned in a list.
As with the sql method, you can use placeholders and pass the values as the remaining parameters.
People->advanced_sql(' SELECT artist.oid FROM artist,track WHERE track.artist_name = artist.name AND track.length > ? ORDER BY artist.name', 100 );
This will be slower than sql - there will be another SQL query on the db for every row returned. That's life. There is much scope here for optimization - the simplest thing to do might be to return a list of proxies instead..
Also consider that the SQL statement you're passing will be just thrown at the database. You can call Object->advanced_sql('DROP DATABASE people') and bad things will happen. This is, of course, almost equally true for the sql method, but it's easier to break things with this one.
The API isn't yet stabilised, so please keep an eye on the Changes file where incompatible changes will be noted.
This module was influnced by James Duncan and Piers Cawley's Pixie object persistence framework, and Class::DBI, by Michael Schwern and Tony Bowden (amongst many others), as well as suggestions from various people within Fotango.
Copyright 2004 Fotango. All Rights Reserved.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.