|
|
| |
T2(3) |
User Contributed Perl Documentation |
T2(3) |
T2 - Object Relational mapping system
use T2::Storage;
# T2::Storage class provides Tangram::Storage API and
# loads schemas
my $storage = T2::Storage->open("appName");
my (@ids) = $storage->insert(@some_objects);
# T2::Schema structures can be manipulated in the same way
my $schema_storage = T2::Storage->open("schema");
my $schema = T2::Schema->load("appName", $schema_storage);
my @classes = $schema->classes;
$schema->classes_remove(17); # remove a random class
$schema_storage->update($schema);
The T2 module is a base for the refactoring of the now quite stable Tangram
Object-Relational mapper.
In a nutshell, it lets you store objects - which have to be
described to a similar level that you would describe a database to store
them - into any SQL store. Currently, this is tested on PostgreSQL, MySQL,
Oracle and Sybase a lot, though in general database-specific extensions to
SQL, such as triggers, stored procedures, etc are avoided. So, if DBI
installs and tests successfully with your database, there is a good chance
that T2 will work with it too.
The only current requirement is that objects that have tables
associated with them are implemented via hashes. You also have to be able to
describe all of the fields for those root objects. Individual fields of
stored objects may be arbitrarily complex.
If you are familiar with DBI, it is somewhat similar to bless'ing
the structures returned by
"$dbh->fetchrow_hashref", except that
references and collections to other objects in the store are loaded `on
demand' (aka Lazy-loading).
The T2:: namespace currently contains:
- T2::Storage
- T2::Storage is a convenience wrapper for Tangram::Storage. Hence, the
object it returns provides the complete Tangram 2 API. It contains a
constructor that automatically grabs configuration information (such as,
database location, schema details, etc), and connects to the database.
It makes simple programs, for existing applications that have
an established schema very simple. Getting the schema structures there
in the first place, however, is not terribly straightforward. Yet.
As more of the Tangram core is ported over the the new
T2::Storage class, the documentation here and in T2::Storage will be
completed. For now, Tangram and Tangram::Storage are the best starting
points.
- T2::Schema, T2::Class, etc.
- The T2::Schema structures are the Tangram schema, expressed as
Class::Tangram objects. These are hence easily storable in a T2 data
store. Or a Pixie/MLDBM/etc store, for that matter.
You might be asking, "how does one write a FUQ file?"
One answer is by becoming maintainer of a module, and talking to
people who have looked at a module, and seeing what drawbacks they saw, or
why they didn't take it any further.
- How do I just quickly store an object?
- At the moment, there is no shortcut. You must declare a simple schema that
has the object type (or one of its superclasses) that you wish to store.
Warning: the examples in this section have been quickly
written, and there are probably some minor bugs. If you encounter
problems, please send a message to the mailing list (see SUPPORT).
Creating this structure is a lot easier with the
I'll-release-it-RSN-ware web-based VT2 tool, but here is some example
code to set up a schema file;
my $schema = T2::Schema->new
( T2::Class->new( name => "ExampleClass",
attributes => [ T2::Attribute->new
( type => "perl_dump",
name => "foo",
) ],
);
use Storable qw(freeze);
open FOO, ">etc/myApp.t2";
binmode FOO;
$Storable::Deparse = 1;
print FOO freeze $schema;
close FOO;
Yes, OK, that's not exactly a one-liner. But it should give
you an idea of what's involved. Again, the web-based tool to manage the
above schema structures makes things a lot quicker.
You'd then create a file etc/myApp.dsn, with something
like the following contents:
dsn dbi:mysql:database=myApp
user myApp
auth razamatazz
schema myApp
(yes, this should be YAML. Patches welcome :))
Then, you need to create the user and set up the database. You
can use the t2-migrate-db.pl utility script in the T2
distribution to do the latter;
$ echo 'grant all privileges on myApp.* to myApp@localhost' \
identified by "razamatazz"' | mysql -uroot -p
Password:
$ t2-migrate-db.pl --read --deploy myApp
...
$
Still with me? Good. Then the script to actually use
the code is simple;
use T2::Storage;
my $storage = T2::Storage->open("myApp");
# this line makes the classes for you, if you didn't
# already have ExampleClass written.
$storage->schema->generator();
# stick an object in the DB and return an object ID
my $oid = $storage->insert(new ExampleClass(foo => "bar"));
# anything in $exampleClass->foo can be stored (via
# perl_dump mapping)
use Whatever;
# fetch the object back
my $exampleClass = $storage->load($oid);
$exampleClass->set_foo( { bar => new Whatever() } );
$storage->update($exampleClass);
$storage->insert(new ExampleClass
(foo => [ 1, 2, $exampleClass ]));
See Tangram::Tour for a more detailed example of how to
manipulate objects in the database, and Class::Tangram for more
information on how to use the generated constructors and accessors (eg,
"new
ExampleClass" and
"set_foo" in the above example).
You don't have to use Class::Tangram classes in a T2
store. But they are very well behaved OO classes that communicate via
message passing exclusively, and export the information needed by T2 to
store them in a package global. So they're convenient.
- How do I just quickly get an object out?
- If you still have the object ID, you can fetch it by that;
my $user = $storage->load($user_oid);
If that user has a reference to another storage object in it
(what would normally be accomplished using an ID into another table in
SQL), then you can just access the value; it is `demand paged' / `lazy
loaded' via Data::Lazy or an equivalent. For example;
my $details = $user->details;
If the referant object is already in memory, then the
in-memory version is used instead of being explicitly loaded from the
database.
Otherwise, you can use the OO query format explained in much
more detail in Tangram::Tour;
my $remote_session = $storage->remote("MySession::Class");
my ($session) = $storage->select
($remote_session,
$remote_session->{SID} eq $somesid);
The query format is flexible enough to represent virtually any
SQL query. The "$remote_session" object is an object which
represents an object in the database of the given type. So, the
expression "$remote_session-"{SID} eq
$somesid> returns an object that represents
all MySession::Class objects that have a "SID" of
$somesid.
Generally, people either think that this syntax is the
cleanest method of expressing relationships in a non-SQL way possible,
or, as one of the Pixie authors put it, you 'turn running and
screaming'.
- OK, now how do I change the schema?
- Simply write a new etc/myApp.t2 schema file. Modify the script
above and re-run it.
- How does Tangram compare to XXX?
- First, you should have a look at the POOP (that's Perl Object Oriented
Persistence ":)") summary at
<http://poop.sf.net/>.
In a nutshell, there are two types of persistence tools; SQL
abstractors (eg, Alzabo, Class::DBI) and true Object Persistence tools
(eg Pixie, Tangram).
The SQL abstractors tend to require that all of your objects
derive from a common base class. This is encouraged with T2, but not
required.
The Object Persistence tools will generally let you store
pretty much anything, without `intruding' on your objects. In theory,
this means that they may easily be loaded from one storage class and
thrown into another.
- What Query languages do I use?
- See Tangram::Tour for a run-down on the query format.
- How can I manage schemas?
- Using the web-based tool that manages these T2::Schema data structures in
a Tangram store, and the supplied utility scripts. The web-based
application is expected to be released by Q2 2004.
- Why bother with schema maintenance at all?
- At some level, your application has a schema governing it.
The idea with these modules is that you express it all in a
standard way in one place, rather than keeping some in your head, some
in the module source, some in the database tables...
- Wouldn't it be faster to roll your own indexes?
- There is an argument that it is simpler to opt for *very* simple data
persistence, and just use your own objects for the indexes.
The answer is, this really sucks for concurrency and
transaction safety. Especially as the size of the index grows. This is
one of the reasons you might want to use a database in the first place
:-).
Support for bugs is provided on a "politely state your problem with a test
case to demonstrate the bug, and if you're lucky, someone will fix it for
you" basis by the Tangram community.
The current home page, including information on the mailing list,
IRC channels, SVN servers, etc is at
<http://tangram.utsl.gen.nz/>.
Jean-Louis Leroy is the original author of Tangram 1 and 2.
Sam Vilain is the author of T2::* and Class::Tangram, and current
maintainer of Tangram.
Changes are known to be contributed to the combined Tangram and T2
code base from:
- Gabor Herr
- Marian Kelc
- Aaron Mackey
- Kurt Stephens
- Kate Pugh
Most of the code in this collection is dual GPL / Perl Artistic license.
However, at least some of it is purely GPL. So, the combined license of this
collection is currently the GPL.
For information on the GPL, please see
<http://www.gnu.org/>.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc. |