Name

Object::Relation::Handle - The Object::Relation data storage class

Synopsis

use Object::Relation::Handle;
use Object::Relation::Biz::Subclass;
my $iter = Object::Relation::Handle->query('Object::Relation::Biz::SubClass' =>
                                  attr => 'value');

Description

This class handles all of the work necessary to communicate with back-end storage systems. Object::Relation::Handle itself is an abstract class; its subclasses will implement its interface for different storage devices: RDBMSs, OODBMSs, XML Files, LDAP, or whatever. The canonical storage implementation is Object::Relation::Handle::DB::Pg, for PostgreSQL 8.0 or later. Others might include Object::Relation::Handle::DB::SQLite for SQLite, Object::Relation::Handle::DB::mysql for MySQL 5.0 or later, and Object::Relation::Handle::LDAP.

Constructors

new

my $store = Object::Relation::Handle->new(
    class => 'DB::Pg',
    cache => 'Memcached',
    dsn   => 'dbi:Pg:dbname=obj_rel',
    user  => 'obj_rel',
    pass  => 'obj_rel',
);

Creates and returns a new store object. This is a factory constructor; it will return an object of the subclass specified by the class parameter. The default parameters are:

class

The subclass of Object::Relation::Handle to use. If the class is under the Object::Relation::Handle namespace, you can leave out "Object::Relation::Handle". Otherwise, use the full class name. Defaults to "DB::SQLiite".

cache

The subclass of Object::Relation::Cache to use for caching. If the class is under the Object::Relation::Cache namespace, you can leave out "Object::Relation::Cache". Otherwise, use the full class name. Defaults to "File".

All other parameters are specific to subclasses of Object::Relation::Handle; see the revelant subclass for details.

Instance Methods

lookup

my $bric_obj = $store->lookup($class, uuid => $uuid);
$bric_obj = $store->lookup($class, unique_attr => $value);

Method to look up objects in the Object::Relation data store by a unique identifier. Most often the identifier used will be globally unique object identifier. However, for Object::Relation classes that allow unique identifiers other than UUIDs -- that is, system-wide (rather than globally) unique identifiers -- then an appropriate key/value pair may be used for the lookup. No SQL wildcards or regular expressions will be allowed. The lookup value must be a complete value.

Most often this method will not be used directly, but rather by calling the lookup() method on Object::Relation classes.

Throws:

Exception::DA

query

my $iter = $store->query( $class => @search_params );
$iter = $store->query( $class => @search_params,
                        \%constraints );

Use this method to search the Object::Relation data store for all of the objects of a particular Object::Relation class that meet a specified set of search parameters. The $class argument is required, while the search parameters are optional but highly recommended (otherwise it will "find" all of the objects in the class). See Search Parameters Explained for details on specifying search parameters. Returns a Object::Relation::Collection object that may be used to fetch each of the objects found by the search. If no objects are found, query returns an empty iterator. See Object::Relation::Collection for details on its interface. See the documentation for the query method in a particular class for a list of object attributes to search by in that class.

An optional hash reference of search modifiers may be passed in as the final argument to query. The available search modifiers are:

order_by
my $iter = $store->query( $class, @search_params,
                           { order_by => $attr } );

The name of an object attribute or an array reference of object attributes to sort by. All sorting is done in a case-insensitive fashion. The actual sort order is dependent on the ordering rules of your data store. Do not pass "uuid" as a sort parameter, as it will always be used for sorting, anyway. If this modifier isn't passed in, the class will select a default or set of default attributes to sort by.

sort_order
my $iter = $store->query( $class, @search_params,
                           { order_by   => $attr,
                             sort_order => ASC } );

The direction in which to sort the the order_by attributes. The possible values are ASC and DESC. If order_by is a single attribute, then sort_order should be a single value, or will default to ASC. If order_by is an array of attributes, then sort_order may also be an array of directions; any directions missing for a corresponding order_by attribute will default to ASC. By default, all searches will be ASC.

Passing sort_order without a corresponding order_by constraint will have no effect.

limit
my $iter = $store->query( $class, @search_params,
                           { limit => 50 } );

Limits the number of objects returned to a given number. This is useful for search interfaces that need to paginate search results without loading thousands or even millions of objects just to load 50 of them. Best used in combination with offset.

offset
my $iter = $store->query( $class, @search_params,
                           { limit  => 50 } );
                             offset => 200 );

Returns an iterator of Object::Relation objects starting with the number offset in the search results. In the above example, the call to query would return only 50 objects, starting with the 200th object found in the search. This is implemented in such a way that the data store does all the work and returns only the results desired. It is therefore a very efficient way to fetch results for pagination.

Passing offset without a corresponding limit constraint will have no effect.

Throws:

Exception::DA

query_uuids

my @uuids = $store->query_uuids( $class => @search_params );
my $uuids_aref = $store->query_uuids( $class => @search_params );

Returns a list or array reference of UUIDs for the the class $class based on the search parameters. See Search Parameters Explained for details on specifying search parameters. Returns an empty list in an array context and an empty array reference in a scalar context when no results are found.

Throws:

Exception::DA

squery_uuids

my @uuids = $store->squery_uuids( $class => "@search_params" );
my $uuids_aref = $store->squery_uuids( $class => "@search_params" );

Same as query_uuids but uses a string search.

count

my $count = $store->count( $class => @search_params );

Returns a count of the number of objects that would be found by query (or the number of UUIDs that would be returned by query_uuids()) for the class $class based on the search parameters. See Search Parameters Explained for details on specifying search parameters. Returns "0" when no results would be found in the search.

The count() method will most often be called to determine how many pages to provide links for when paginating search results in the UI. Therefore, for purposes of efficiency, the result of a call to count() will be cached, so that subsequent calls to count() with the same parameters will not incur the database overhead.

Throws:

Exception::DA

save

$bric_obj = $store->save($bric_obj);

Saves any changes to the Object::Relation object to the data store. Returns the Object::Relation object on success and throws an exception on failure. No part of the Object::Relation object or its parts will ever be saved unless and until the save() method is called. The only exception is when the Object::Relation object is contained in another object (such as via a has-a relationship), when that other will be saved, as well. That is to say, save() saves the Object::Relation object and each of its contained objects.

The save() method will also delete an object from the data store if its state is set to PURGE. This feature should be used with care, however, since in an RDBMS, at least, DELETEs will likely cascade.

For storage back-ends that support transactions, all transaction handling will be managed by save(). When called, save() will start a transaction. At the end of the method, it will either commit the transaction or rollback the transaction, depending on whether an error was thrown. If the transaction is rolled back, the exception will be propagated to the caller. Any contained objects that have their save() methods called from within the context of the call to the containing object's save() method will be a part of the same transaction. This approach keeps transactions neatly encapsulated in a single call to save(), mirroring the encapsulation of Object::Relation objects.

Throws:

Error::Undef
Error::Invalid
Exception::DA