.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Tangram::Intro 3pm" .TH Tangram::Intro 3pm "2015-11-09" "perl v5.20.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Tangram::Intro \- an introduction to Tangram .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 2 \& # http://www.faqs.org/rfcs/rfc2324.html \& perl \-MNet::HTCPCP \-le \*(AqNet::HTCPCP\->new("BREW")\->send\*(Aq \& \& perldoc Tangram::Intro .Ve .SH "YIN AND YANG OF OBJECT PERSISTENCE" .IX Header "YIN AND YANG OF OBJECT PERSISTENCE" There are yin and yang approaches to object persistence. Are you a yin programmer or a yang programmer? .IP "\fByin\fR" 4 .IX Item "yin" (without, empty) \- \*(L"I just want to store my objects\*(R" .IP "\fByang\fR" 4 .IX Item "yang" (with, full) \- \*(L"I want my database to represent my object structure\*(R" .PP Please skip to the introduction that suits you. .SS "\s-1YIN OBJECT PERSISTENCE \s0(A \s-1LA PIXIE\s0)" .IX Subsection "YIN OBJECT PERSISTENCE (A LA PIXIE)" One yin approach is to have a single table of objects \- .PP .Vb 3 \& +\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ \& | ID | DATA | \& +\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-+ .Ve .PP This is the raw technique used by modules like \s-1MLDBM. \s0 Stick objects in, get a tag (or, insert with a tag), and later present that tag to get the objects out. .PP Modules like Pixie extend this concept, to allow you to have objects that are \fIpersistent\fR (ie, have been stored and could be retrieved again by \s-1ID\s0 or name), inside other structures that are also persistent. This is achieved without storing the same structure twice, without having to fetch all objects that are in a single persistent structure, and without requiring that the objects being stored even know that they are being stored. .PP Fantastic. This method is fine for any application that doesn't mind single threading data manipulation on objects. .PP Enough banter, let's see some code; here's a project schema: .PP .Vb 1 \& package MyProject::Tangram; \& \& use Heritable::Types; \& use Tangram::Core; \& use Tangram::Type::Dump::Any; \& \& our $schema = \& Tangram::Schema\->new \& ( { classes => \& [ HASH => { \& fields => { \& idbif => # poof! \& undef \& }, \& }, \& ], \& } ); \& \& sub db { Tangram::Storage\->new($schema, @_) } .Ve .PP This defines a sort of \*(L"store anything\*(R" schema. You could deploy your database like this: .PP .Vb 4 \& my $dbh = DBI\->connect \& ("dbi:mysql:tangram", "user", "pass"); \& Tangram::Relational\->deploy ( $MyProject::Tangram::schema, \& $dbh ); .Ve .PP And then shove objects in and out like this: .PP .Vb 3 \& use MyProject::Tangram; \& my $storage = MyProject::Tangram::db \& ("dbi:mysql:tangram", "user", "pass"); \& \& my $object = bless { first_name => "Homer", \& last_lame => "Simpson", \& }, "NaturalPerson"; \& my $oid = $storage\->insert($object); \& \& my $homer = $storage\->load($oid); .Ve .PP If this Pixie-like functionality is all you're after, then you can stop there, and isn't much slower than Pixie. You also get the choice of whether you want to freeze data structures in your database via \&\*(L"Data::Dumper\*(R", \*(L"Storable\*(R" or \*(L"\s-1YAML\*(R".\s0 .SS "\s-1YANG OBJECT PERSISTENCE\s0" .IX Subsection "YANG OBJECT PERSISTENCE" If you wish to enable concurrency without paying a large performance penalty for most standard types of data access, then you may need to extract single parts of your objects into columns. That way, you can make the most use of your database's (hopefully) highly tuned and refined ability to cache and manipulate data indices. .PP In that case, you may choose to start with mapping all of your object's properties to database columns (as was the only option before Tangram 2.08): .PP .Vb 1 \& package MyProject::Tangram; \& \& use Tangram::Core; \& \& our $schema = \& Tangram::Schema\->new \& ( { classes => \& [ NaturalPerson => { \& fields => { \& string => { \& }, \& integer => { \& } \& }, \& }, \& ], \& } ); \& \& sub db { Tangram::Storage\->new($schema, @_) } .Ve .PP Tangram has been transaction-savvy since version 1. So long as you are careful to flush Tangram's object cache, before you start doing selects that lock rows for update, then you can easily write transaction protected programs. .SH "FURTHER READING" .IX Header "FURTHER READING" The original Tangram::Tour is still worth reading \- but bear in mind the above \- Tangram can map schemas richly or simply, and the choice is up to you. See also Tangram::Sucks for the things which need to be improved.