Persistence::Relationship::ManyToMany - Many to many relationship


Persistence-Entity documentation Contained in the Persistence-Entity distribution.

Index


Code Index:

NAME

Top

Persistence::Relationship::ManyToMany - Many to many relationship

CLASS HIERARCHY

Top

 Persistence::Relationship
    |
    +----Persistence::Relationship::ManyToMany




SYNOPSIS

Top

    use Persistence::Relationship::ManyToMany ':all';

#.... entities definition

    my $entity_manager = Persistence::Entity::Manager->new(name => 'my_manager', connection_name => 'test');

    my $emp_project_entity = Persistence::Entity->new(
        name    => 'emp_project',
        alias   => 'ep',
        primary_key => ['projno', 'empno'],
        columns => [
            sql_column(name => 'projno'),
            sql_column(name => 'empno'),
            sql_column(name => 'leader'),
        ],
    );

    my $emp_entity = Persistence::Entity->new(
        name    => 'emp',
        alias   => 'ep',
        primary_key => ['empno'],
        columns => [
            sql_column(name => 'empno'),
            sql_column(name => 'ename', unique => 1),
            sql_column(name => 'job'),
            sql_column(name => 'deptno'),
        ],
        value_generators => {empno => 'emp_gen'}, 
        to_many_relationships => [
            sql_relationship(target_entity => $emp_project_entity,
            join_columns => ['empno'], order_by => 'empno, projno')
        ]
    );

    my $project_entity = Persistence::Entity->new(
        name    => 'project',
        alias   => 'pr',
        primary_key => ['projno'],
        columns => [
            sql_column(name => 'projno'),
            sql_column(name => 'name', unique => 1),
        ],
        value_generators => {projno => 'project_gen'},
        to_many_relationships => [
            sql_relationship(target_entity => $emp_project_entity,
            join_columns => ['projno'], order_by => 'projno, empno')
        ]
    );

    $entity_manager->add_entities($emp_project_entity, $emp_entity, $project_entity);

    # object mapping

    package Project;

    use Abstract::Meta::Class ':all';
    use Persistence::Entity ':all';
    use Persistence::ORM ':all';

    entity 'project';
    column projno => has('$.id');
    column name => has('$.name');

    package Employee;

    use Abstract::Meta::Class ':all';
    use Persistence::Entity ':all';
    use Persistence::ORM ':all';

    entity 'emp';
    column empno=> has('$.id');
    column ename => has('$.name');
    column job => has '$.job';

    many_to_many 'project' => (
        attribute        => has('%.projects' => (associated_class => 'Project'), index_by => 'name'),
        join_entity_name => 'emp_project',
        fetch_method     => LAZY,
        cascade          => ALL,
    );

DESCRIPTION

Top

Represents many to many relationship. Supports eager, lazy fetch, cascading operation (inert/update/delete).

EXPORT

Top

many_to_many by ':all' tag.

ATTRIBUTES

join_entity_name

Join entity name.

METHODS

many_to_many
deserialise_attribute

Deserialises relation attribute

insert

Inserts relationship data.

merge

Merges relationship data.

delete

Deletes many to many association.

_associate_relationship_data

SEE ALSO

Top

Persistence::Relationship Persistence::Entity Persistence::Entity::Manager Persistence::ORM

COPYRIGHT AND LICENSE

Top

AUTHOR

Top

Adrian Witas, adrian@webapp.strefa.pl


Persistence-Entity documentation Contained in the Persistence-Entity distribution.
package Persistence::Relationship::ManyToMany;

use strict;
use warnings;

use vars qw(@EXPORT_OK %EXPORT_TAGS $VERSION);

use Abstract::Meta::Class ':all';
use base qw (Exporter Persistence::Relationship);
use Carp 'confess';

$VERSION = 0.01;

@EXPORT_OK = qw(many_to_many);
%EXPORT_TAGS = (all => \@EXPORT_OK);

has '$.join_entity_name' => (required => 1);


sub many_to_many {
    my $package = caller();
    __PACKAGE__->add_relationship($package, @_);
}


sub deserialise_attribute {
    my ($self, $object, $entity_manager, $orm) = @_;
    my $entity = $entity_manager->entity($orm->entity_name);
    my $target_entity = $entity_manager->entity($self->name)
        or confess "cant find entity" . $self->name;
    my $join_entity = $entity_manager->entity($self->join_entity_name);
    my $relation = $entity->to_many_relationship($self->join_entity_name);
    my %fields_values = $orm->column_values($object);
    my %join_values = $entity->_join_columns_values($relation, \%fields_values);
    return unless(map {$join_values{$_} ? ($_) : () }  keys %join_values);
    my $condition = SQL::Entity::Condition->struct_to_condition(map {$join_entity->column($_), $join_values{$_}} keys %join_values);
    my $attribute = $self->attribute;
    my @rows =  $target_entity->find($attribute->associated_class,  $condition);
    if (@rows) {
        my $mutator = $attribute->mutator;
        $object->$mutator(\@rows);
    }
}


sub insert {
    my ($self, $orm, $entity, $unique_values, $object) = @_;
    $self->_associate_relationship_data($orm, $entity, $unique_values, $object, 'insert');
}


sub merge {
    my ($self, $orm, $entity, $unique_values, $object) = @_;
    $self->_associate_relationship_data($orm, $entity, $unique_values, $object, 'merge');
}


sub delete {
    my ($self, $orm, $entity, $unique_values, $object) = @_;
    my $join_entity_name = $self->join_entity_name;
    my $attribute = $self->attribute;
    my $values = $self->values($object);
    my $entity_manager = $entity->entity_manager;
    my $target_entity = $entity_manager->entity($self->name);
    my $reflective_orm =  $entity_manager->find_entity_mappings($attribute->associated_class);
    my $join_values = $orm->join_columns_values($entity, $join_entity_name, $object);
    my $join_entity = $entity_manager->entity($join_entity_name);
    foreach my $association_object (@$values) {
        $join_entity->delete(
            %$join_values,
            $reflective_orm->join_columns_values($target_entity, $join_entity_name, $association_object)
        );
    }
}


sub _associate_relationship_data {
    my ($self, $orm, $entity, $unique_values, $object, $operation) = @_;
    my $join_entity_name = $self->join_entity_name;
    my $attribute = $self->attribute;
    my $values = $self->values($object);
    my $entity_manager = $entity->entity_manager;
    my $target_entity = $entity_manager->entity($self->name);
    my $reflective_orm =  $entity_manager->find_entity_mappings($attribute->associated_class);
    my $join_values = $orm->join_columns_values($entity, $join_entity_name, $object);
    
    my $reflective_relation = $target_entity->to_many_relationship($join_entity_name);
    my $join_entity = $entity_manager->entity($join_entity_name);
    
    foreach my $association_object (@$values) {
        $entity_manager->merge($association_object);
        $join_entity->$operation(
            %$join_values,
            $reflective_orm->join_columns_values($target_entity, $join_entity_name, $association_object)
        );
    }
}


1;    

__END__

1;