| Persistence-Entity documentation | Contained in the Persistence-Entity distribution. |
Persistence::ORM - Object-relational mapping.
package Employee;
use Abstract::Meta::Class ':all';
use Persistence::ORM ':all';
entity 'emp';
column empno => has('$.no') ;
column ename => has('$.name');
Object-relational mapping module.
entity column trigger to_one one_to_many many_to_many LAZY EAGER NONE ALL ON_INSERT ON_UPDATE ON_DELETE by 'all' tag
class name
entity name.
A map between database column and object attribute
Assocation to LOB objects definition.
Assocation to objects relationship definition.
Defines tigger that will execute on one of the following event before_insert after_insert before_update after_update before_delete after_delete, on_fetch Takes event name as first parameter, and callback as secound parameter.
$entity_manager->trigger(before_insert => sub {
my ($self) = @_;
#do stuff
});
Name of the class that is an adapter to meta object protocols. That class have to implements Persistence::Attribute interface.
Returns object creation method. Allowed values: bless or new
Cache for the attributes_to_columns method result
Cache for the columns_to_attributes method result
Cache for the columns_to_storage_attributes method result
Creates a meta entity class.
Returns meta enity class. Takes optionally package name as parameter.
Adds mapping between column name and related attribute. Takes column name and attribute object as parameter.
column ('column1' => has '$.attr1');
Adds mapping between lob column name and related attribute.
lob 'lob_column' => (
attribute => has('$.photo'),
fetch_method => LAZY,
);
Converts passed in data structure to attributes
Converts passed in data structure to lob attributes
Creates a meta attribute
Adds lob column. Takes lob column name, attribute name;
Deserialises resultset to object.
Returns join columns values for passed in relation
Return unique columns values
Return primary key values
Validates triggers types
Returns column name. Takes attribute name.
Transforms column values to the hash that can be blessed as an object. Takes hash ref of column_values
Transforms column values to the object attribute value hash. Takes hash ref of column_values
Transforms objects attributes to column values Takes object, optionally required columns. (by default all colunms)
Returns column values. Takes attribute values hash.
Abstract::Meta::Class Persistence::Entity::Manager SQL::Entity
The SQL::Entity::ORM module is free software. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.
Adrian Witas, adrian@webapp.strefa.pl
| Persistence-Entity documentation | Contained in the Persistence-Entity distribution. |
package Persistence::ORM; use strict; use warnings; use Abstract::Meta::Class ':all'; use Persistence::Attribute::AMCAdapter; use Persistence::Relationship ':all'; use Persistence::LOB; use Persistence::Relationship::ToOne ':all'; use Persistence::Relationship::OneToMany ':all'; use Persistence::Relationship::ManyToMany ':all'; use vars qw(@EXPORT_OK %EXPORT_TAGS $VERSION); use Carp 'confess'; use base 'Exporter'; $VERSION = 0.04; @EXPORT_OK = qw(entity column trigger to_one one_to_many many_to_many lob LAZY EAGER NONE ALL ON_INSERT ON_UPDATE ON_DELETE); %EXPORT_TAGS = (all => \@EXPORT_OK);
has '$.class' => ( required => 1, on_change => sub { my ($self, $attribute, $scope, $value_ref) = @_; mapping_meta($$value_ref, $self); } );
has '$.entity_name' => (required => 1);
has '%.columns' => ( item_accessor => '_column', associated_class => 'Persistence::Attribute', index_by => 'column_name', on_validate => sub { my ($self, $attribute, $scope, $value_ref) = @_; my $values = $$value_ref; if (ref($values) eq 'HASH') { my $class = $self->class; foreach my $k (keys %$values) { my $value = $values->{$k}; $values->{$k} = $self->_create_meta_attribute($value, $class, $k) if(ref($value) eq 'HASH') } } } );
has '%.lobs' => (item_accessor => '_lob', associated_class => 'Persistence::LOB', the_other_end => 'orm');
has '%.relationships' => (item_accessor => '_relationship', associated_class => 'Persistence::Relationship', index_by => 'attribute_name', the_other_end => 'orm');
{ has '%.triggers' => ( item_accessor => '_trigger', on_change => sub { my ($self, $attribute, $scope, $value, $key) = @_; if($scope eq 'mutator') { my $hash = $$value; foreach my $k (keys %$hash) { $self->validate_trigger($k. $hash->{$k}); } } else { $self->validate_trigger($key, $$value); } $self; }, ); }
has '$.entity_manager' => (transistent => 1);
has '$.mop_attribute_adapter' => ( default => 'Persistence::Attribute::AMCAdapter', );
has '$.object_creation_method' => ( default => 'bless', on_change => sub { my ($self, $attribute, $scope, $value) = @_; confess "invalid value for " . __PACKAGE__ . "::object_creation_method - allowed values(bless | new)" if ($$value ne 'bless' && $$value ne 'new'); $self; } );
has '$._attributes_to_columns';
has '$._columns_to_attributes';
has '$._columns_to_storage_attributes';
sub entity { my ($name, $package) = @_; $package ||= caller(); __PACKAGE__->new(entity_name => $name, class => $package); } { my %meta;
sub mapping_meta {
my ($package, $value) = @_;
$package ||= caller();
$meta{$package} = $value if defined $value;
$meta{$package};
}
}
sub column { my ($name, $attribute) = @_; my $attr_class = 'Persistence::Attribute'; my $package = caller(); my $self = mapping_meta($package) or confess "no entity defined for class $package"; my $attribute_class = $self->mop_attribute_adapter; $attribute = $attribute_class->new(attribute => $attribute, column_name => $name) unless $attribute->isa('Persistence::Attribute'); $self->add_columns($attribute); }
sub lob { my ($name, %args) = @_; my $attribute = $args{attribute}; my $attr_class = 'Persistence::Attribute'; my $package = caller(); my $self = mapping_meta($package) or confess "no entity defined for class $package"; my $attribute_class = $self->mop_attribute_adapter; $args{attribute} = $attribute_class->new(attribute => $attribute, column_name => $name) unless $attribute->isa('Persistence::Attribute'); $self->add_lobs(Persistence::LOB->new(%args)); }
sub covert_to_attributes { my ($self, $columns) = @_; my $class = $self->class; my $attribute_class = $self->mop_attribute_adapter; my $result = {}; for my $column(keys %$columns) { my $meta_attribute = $columns->{$column}; my $attribute = $attribute_class->find_attribute($class, $meta_attribute->{name}); unless ($attribute) { $attribute = $self->_create_meta_attribute($meta_attribute, $class, $column); } else { $attribute = $attribute_class->new(attribute => $attribute, column_name => $column); } $result->{$column} = $attribute; } $result; }
sub covert_to_lob_attributes { my ($self, $lobs) = @_; my $class = $self->class; my $attribute_class = $self->mop_attribute_adapter; my $result = {}; for my $lob (@$lobs) { my $column = $lob->{name}; my $fetch_method = $lob->{fetch_method}; my $attribute_name = $lob->{attribute}; my $attribute = $attribute_class->find_attribute($class, $attribute_name); unless ($attribute) { $attribute = $self->_create_meta_attribute({name => $attribute_name}, $class, $column); } else { $attribute = $attribute_class->new(attribute => $attribute, column_name => $column); } $result->{$column} = Persistence::LOB->new( attribute => $attribute, ($fetch_method ? (fetch_method => Persistence::LOB->$fetch_method) :()) ); } $result; }
sub _create_meta_attribute { my ($clazz, $meta_attribute, $class, $column_name) = @_; my $self = mapping_meta($class) or confess "no entity defined for class $class"; my $attribute_class = $self->mop_attribute_adapter; $attribute_class->create_meta_attribute($meta_attribute, $class, $column_name); }
sub add_lob_column { my ($self, $column, $attribute_name, $fetch_method) = @_; $self->add_lobs( Persistence::LOB->new( name => 'column', attribute => $self->attribute($attribute_name), ($fetch_method ? (fetch_method => Persistence::LOB->$fetch_method) :()), ) ); }
sub eager_fetch_lobs { my ($self) = @_; my $lobs = $self->lobs; Persistence::LOB->eager_fetch_filter($lobs); }
sub lazy_fetch_lobs { my ($self) = @_; my $lobs = $self->lobs; Persistence::LOB->lazy_fetch_filter($lobs); }
sub attribute { my ($self, $attribute_name) = @_; my $meta = Abstract::Meta::Class::meta_class($self->class) or confess "cant find meta class defintion (Abstract::Meta::Class) for " . $self->class; my $attribute = $meta->attribute($attribute_name) or confess "cant find attribute ${attribute_name} for class " . $self->class; $attribute; }
sub deserialise { my ($self, $args, $entity_manager) = @_; my $object_creation_method = $self->object_creation_method; my $columns_to_attributes = $self->columns_to_attributes; my $result = $object_creation_method eq 'bless' ? bless ({ $self->storage_attribute_values($args) }, $self->class) : $self->class->new(map { $args->{$_} } keys %$columns_to_attributes); $entity_manager->initialise_operation($self->entity_name, $result); $self->deserialise_eager_relation_attributes($result, $entity_manager); $self->deserialise_eager_lob_attributes($result, $entity_manager); $entity_manager->complete_operation($self->entity_name); $self->run_event('on_fetch', $result); $result; }
sub deserialise_eager_relation_attributes { my ($self, $object, $entity_manager) = @_; my @relations = Persistence::Relationship->eager_fetch_relations(ref($object)); foreach my $relation (@relations) { $relation->deserialise_attribute($object, $entity_manager, $self); } }
sub deserialise_eager_lob_attributes { my ($self, $object, $entity_manager) = @_; my @lobs = $self->eager_fetch_lobs; foreach my $lob (@lobs) { $lob->deserialise_attribute($object, $entity_manager, $self); } }
sub deserialise_lazy_relation_attributes { my ($self, $object, $entity_manager) = @_; my @relations = Persistence::Relationship->lazy_fetch_relations(ref($object)); foreach my $relation (@relations) { my $name = $relation->attribute->name; $object->$name; } }
sub update_object { my ($self, $object, $column_values, $columns_to_update) = @_; my $columns = $self->columns; $columns_to_update ||= [keys %$column_values]; for my $column_name (@$columns_to_update) { my $attribute = $columns->{$column_name} or next; $attribute->set_value($object, $column_values->{$column_name}); } }
sub join_columns_values { my ($self, $entity, $relation_name, $object) = @_; my $relation = $entity->to_many_relationship($relation_name); my $pk_values = $self->column_values($object, $entity->primary_key); unless ($entity->has_primary_key_values($pk_values)) { my $values = $self->unique_values($object, $entity); $pk_values = $self->retrive_primary_key_values($values); } $entity->_join_columns_values($relation, $pk_values); }
sub unique_values { my ($self, $object, $entity) = @_; my @unique_columns = map { $_->name } $entity->unique_columns;; $self->column_values($object, $entity->primary_key, @unique_columns); }
sub primary_key_values { my ($self, $object, $entity) = @_; $self->column_values($object, $entity->primary_key); }
sub trigger { my ($event_name, $code_ref) = @_; my $attr_class = 'Abstract::Meta::Attribute'; my $package = caller(); my $mapping_meta = mapping_meta($package) or confess "no entity defined for class $package"; $mapping_meta->_trigger($event_name, $code_ref); }
{ my @triggers = qw(before_insert after_insert before_update after_update before_delete after_delete on_fetch); sub validate_trigger { my ($self, $name, $value) = @_; confess "invalid trigger name: $name , must be one of " . join(",", @triggers) unless (grep {$name eq $_} @triggers); confess "secound parameter must be a callback" unless ref($value) eq 'CODE'; } }
sub run_event { my ($self, $name, @args) = @_; my $event = $self->_trigger($name); $event->($self, @args) if $event; }
sub attributes_to_columns { my ($self) = @_; my $attributes_to_columns = $self->_attributes_to_columns; return $attributes_to_columns if $attributes_to_columns; my $columns = $self->columns; my $result = {}; foreach my $k (keys %$columns) { $result->{$columns->{$k}->name} = $k; } $self->_attributes_to_columns($result); return $result; }
sub columns_to_attributes { my ($self) = @_; my $columns_to_attributes = $self->_columns_to_attributes; return $columns_to_attributes if $columns_to_attributes; my $columns = $self->columns; my $result = {}; foreach my $k (keys %$columns) { $result->{$k} = $columns->{$k}->name; } my $lobs = $self->lobs; foreach my $k (keys %$lobs) { my $attribute = $lobs->{$k}->attribute; $result->{$attribute->column_name} = $attribute->name; } $self->_columns_to_attributes($result); return $result; }
sub columns_to_storage_attributes { my ($self) = @_; my $columns_to_storage_attributes = $self->_columns_to_storage_attributes; return $columns_to_storage_attributes if $columns_to_storage_attributes; my $columns = $self->columns; my $result = {}; foreach my $k (keys %$columns) { $result->{$k} = $columns->{$k}->storage_key; } $self->_columns_to_storage_attributes($result); return $result; }
sub attribute_to_column { my ($self, $attribute_name) = @_; my $attributes_to_columns = $self->attributes_to_columns; $attributes_to_columns->{$attribute_name}; }
sub storage_attribute_values { my ($self, $column_values) = @_; my $columns = $self->columns; my $columns_to_storage_attributes = $self->columns_to_storage_attributes; my %result = map { ($columns_to_storage_attributes->{$_}, $column_values->{$_})} keys %$columns; wantarray ? (%result) : \%result; }
sub attribute_values { my ($self, $column_values) = @_; my $columns = $self->columns; my $columns_to_attributes = $self->columns_to_attributes; my %result = map { ($columns_to_attributes->{$_}, $column_values->{$_} )} keys %$columns; wantarray ? (%result) : \%result; }
sub column_values { my ($self, $obj, @columns) = @_; my $columns_to_attributes = $self->columns_to_attributes; my $lobs = $self->lobs; @columns = (keys %$columns_to_attributes) unless @columns; my %result = map { my $accessor = $columns_to_attributes->{$_}; ($_, $obj->$accessor)} @columns; wantarray ? (%result) : \%result; }
sub attribute_values_to_column_values { my ($self, %args) = @_; my $attributes_to_columns = $self->attributes_to_columns; my %result; for my $k(keys %args) { my $column = $attributes_to_columns->{$k} || $k; $result{$column} = $args{$k}; } (%result); } 1; __END__
1;