File Coverage

blib/lib/Persistence/Entity/Manager.pm
Criterion Covered Total %
statement 22 24 91.6
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 30 32 93.7


line stmt bran cond sub pod time code
1             package Persistence::Entity::Manager;
2              
3 17     17   1086929 use strict;
  17         41  
  17         680  
4 17     17   96 use warnings;
  17         35  
  17         870  
5 17     17   197 use vars qw($VERSION);
  17         33  
  17         1132  
6              
7             $VERSION = 0.03;
8              
9 17     17   1241 use Abstract::Meta::Class ':all';
  17         18332  
  17         3122  
10 17     17   12641 use Persistence::ORM;
  17         63  
  17         1297  
11 17     17   3616 use DBIx::Connection;
  17         221743  
  17         5271  
12 17     17   130 use Carp 'confess';
  17         39  
  17         1565  
13 17     17   12761 use Persistence::Entity ':all';
  0            
  0            
14              
15             use constant TRANSACTION_MANAGEMENT => 'transaction';
16              
17             =head1 NAME
18              
19             Persistence::Entity::Manager - Persistence entity manager.
20              
21             =head1 SYNOPSIS
22              
23             use Persistence::Entity::Manager;
24             use SQL::Entity;
25             use SQL::Entity::Column ':all';
26             use SQL::Entity::Condition ':all';
27              
28             my $entity_manager = Persistence::Entity::Manager->new(
29             name => 'my_manager'
30             connection_name => 'my_connection'
31             );
32              
33             $entity_manager->add_entities(SQL::Entity->new(
34             name => 'emp',
35             primary_key => ['empno'],
36             columns => [
37             sql_column(name => 'ename'),
38             sql_column(name => 'empno'),
39             sql_column(name => 'deptno')
40             ],
41             triggers => {
42             on_fetch => sub { ... },
43             before_insert => sub { ... ]
44             ));
45              
46             {
47             package Employee;
48             use Abstract::Meta::Class ':all';
49             use Persistence::ORM ':all';
50              
51             entity 'emp';
52             column empno => has('$.no') ;
53             column ename => has('$.name');
54             }
55              
56             {
57             my ($emp) = $entity_manager->find(emp => 'Employee', name => 'foo');
58             #object attribute name as part of the condition
59              
60             my (@emp) = $entity_manager->find(emp => 'Employee', sql_cond('ename', 'LIKE' 'a%');
61             }
62              
63             {
64             $entity_manager->begin_work;
65             eval {
66             my $emp = Employee->new(name => 'foo');
67             $entity_manager->insert($user);
68              
69             $emp->set_deptno(10);
70             $entity_manager->update($emp);
71              
72             $entity_manager->delete($emp)
73              
74             my ($emp) = $entity_manager->find(emp => 'Employee', name => 'foo');
75              
76             $entity_manager->commit;
77             };
78              
79             $entity_manager->rollback if($@);
80             }
81              
82              
83             =cut
84              
85             =head1 DESCRIPTION
86              
87             Represets entity manager.
88              
89             =head1 EXPORT
90              
91             None.
92              
93             =head2 ATTRIBUTES
94              
95             =over
96              
97             =item name
98              
99             =cut
100              
101             has '$.name' => (required => 1);
102              
103              
104             =item entities
105              
106             =cut
107              
108             has '%.entities' => (
109             associated_class => 'Persistence::Entity',
110             index_by => 'id',
111             item_accessor => 'entity',
112             the_other_end => 'entity_manager',
113             );
114              
115              
116             =item entities
117              
118             =cut
119              
120             has '%.queries' => (
121             associated_class => 'SQL::Query',
122             index_by => 'name',
123             item_accessor => '_query',
124             );
125              
126              
127             =item connection_name
128              
129             =cut
130              
131             has '$.connection_name' => (
132             on_change => sub {
133             my $self = shift;
134             my $connection = $self->_connection or return $self;
135             $connection->close();
136             $self->set__connection(undef);
137             }
138             );
139              
140              
141             =item _connection
142              
143             =cut
144              
145             has '$._connection' => (transistent => 1);
146              
147              
148             =item persitence_mangement
149              
150             If this option is set, then state of the all fetched, merged or created object by entity manager will be tracked
151             (it's database state is stored in local cache),
152             unless they become detached by calling $entity_manager->detach($obj) or $entity_manager->detach_all
153             or for persitence_mangement = transaction
154              
155             $entity_manager->commit;
156             $entity_manager->rollback;
157              
158             Note:
159             Using this option you must ensure that there are not obsolete objects in the local cache by detching all objects
160             that are no longer in use, it may be resource consuming (memory).
161              
162             If the persitence_mangement option is not set then extra sql will be issued to get object state from database for update, delete.
163              
164             =cut
165              
166             has '$.persitence_mangement' => (default => TRANSACTION_MANAGEMENT());
167              
168              
169             =item _persistence_cache
170              
171             Stores datebase state of the object. The key is the object reference, the values database row.
172              
173             =cut
174              
175             has '%._persistence_cache' => (item_accessor => '_cached_state');
176              
177              
178             =item _lazy_fetch_flag
179              
180             Hash that stores information about lazy retrieve for objects attribute
181              
182             =cut
183              
184             has '%._lazy_fetch_flags' => (item_accessor => '_lazy_fetch_flag');
185              
186             =back
187              
188             =head2 METHODS
189              
190             =over
191              
192             =cut
193              
194              
195             { my %managers;
196              
197             =item initialise
198              
199             =cut
200              
201             sub initialise {
202             my ($self) = @_;
203             $managers{$self->name} = $self;
204             }
205              
206              
207             =item manager
208              
209             Return entity manger object, takes entity manager name as parameter.
210              
211             Persistence::Entity::Manager->new(name => 'manager_name', connection_name => 'connection_nane');
212             #
213             my $entity_manager = Persistence::Entity::Manager->manager('manager_name');
214              
215              
216             =cut
217              
218             sub manager {
219             my ($class, $name) = @_;
220             $managers{$name}
221             or confess "unknown entity manager $name";
222             }
223              
224             }
225              
226              
227             =item find
228              
229             Returns list of objects or resultsets.
230             Takes entity name, class name to which resultset will be casted,
231             (if class name is undef then hash ref will be return instead),
232             list of names parameters that will be used as condition or condition object.
233             For non empty class name resulset state is cached - persitence_mangement option.
234              
235             Note: If class name has the ORM mapping, then name parameters
236             must be objects' attributs . Condition object always should use entity column.
237              
238              
239             my ($emp) = $entity_manager->find(emp => 'Employee', name => 'adrian');
240             or
241              
242             my @emp = $entity_manager->find(emp => 'Employee', sql_cond('ename', 'LIKE', 'a%'));
243             #array of Employee objects.
244              
245             or
246             my @emp = $entity_manager->find(emp => undef, sql_cond('ename', 'LIKE', 'a%'));
247             #array of resultset (hash ref)
248              
249              
250             =cut
251              
252             sub find {
253             my ($self, $entity_name, $class_name, @args) = (@_);
254             my $entity = $self->entity($entity_name) or confess "cant find entity ${entity_name}";
255             $entity->find($class_name, @args);
256             }
257              
258              
259             =item lock
260              
261             Returns and locks list and of objects or resultsets.
262             Takes entity name, class name to which resultset will be casted,
263             (if class name is undef then hash ref will be return instead),
264             list of names parameters that will be used as condition or condition object.
265             For non empty class name resulset state is cached - persitence_mangement option.
266              
267             Note: If class name has the ORM mapping, then name parameters
268             must be objects' attributs . Condition object always should use entity column.
269              
270              
271             my ($emp) = $entity_manager->find(emp => 'Employee', name => 'adrian');
272             or
273              
274             my @emp = $entity_manager->find(emp => 'Employee', sql_cond('ename', 'LIKE', 'a%'));
275             #array of Employee objects.
276              
277             or
278             my @emp = $entity_manager->find(emp => undef, sql_cond('ename', 'LIKE', 'a%'));
279             #array of resultset (hash ref)
280              
281              
282             =cut
283              
284             sub lock {
285             my ($self, $entity_name, $class_name, @args) = (@_);
286             my $entity = $self->entity($entity_name) or confess "cant find entity ${entity_name}";
287             $entity->lock($class_name, @args);
288             }
289              
290              
291             =item condition_converter
292              
293             Converts list of parameters to condition object.
294             Takes class name, list of condition parameters.
295             Note: If class name has the ORM mapping, then name parameters
296             must be objects' attributs . Condition object always should use entity column.
297              
298              
299             my $sql_condition = $entity_manager->condition_converter('Employee', name => 'adrian');
300             #creates ename = 'adrian' sql condition (given that there is mapping between ename column to name attribute).
301              
302              
303             See also L
304              
305             =cut
306              
307             sub condition_converter {
308             my ($self, $class_name, @args) = @_;
309             my $orm = $self->find_entity_mappings($class_name);
310             (@args > 1)
311             ? SQL::Entity::Condition->struct_to_condition(
312             ($orm ? $orm->attribute_values_to_column_values(@args) : @args))
313             : $args[0];
314             }
315              
316              
317             =item query
318              
319             Returns new query object.
320             Takes entity name, optionally class name to which resultset will be casted,
321             (if class name is undef then hash ref will be return instead),
322             For non empty class name resulset state is cached - persitence_mangement option.
323              
324             my $query = $entity_manager->query(emp => undef);
325             $query->set_offset(20);
326             $query->set_limit(5);
327             my @emp = $query->execute(['empno', 'ename']);
328              
329             $query->set_offset(120);
330             $query->set_limit(5);
331             my @emp = $query->execute(undef, deptnp => 10);
332              
333              
334             See also L
335              
336             =cut
337              
338             sub query {
339             my ($self, $entity_name, $class_name) = (@_);
340             my $orm = $self->find_entity_mappings($class_name);
341             my $entity = $self->entity($entity_name) or confess "cant find entity ${entity_name}";
342             my $connection = $self->connection;
343             my $dbms_name = $connection->dbms_name;
344             my $key = $entity->name ."_${dbms_name}_" . ($class_name ||'');
345             my $query = $self->_query($key);
346             unless($query) {
347             $query = Persistence::Entity::Query->new(
348             name => $key,
349             entity => $entity,
350             dialect => $connection->dbms_name,
351             cursor_callback => sub {
352             my ($this, $sql, $bind_variables) = @_;
353             $this->query_setup($connection);
354             $entity->_execute_query($sql, $bind_variables, $class_name);
355             },
356             condition_converter_callback => sub {
357             my (@args) = @_;
358             $self->condition_converter($class_name, @args);
359             }
360             );
361             $self->add_queries($query);
362             }
363             $query;
364             }
365              
366              
367             =item refersh
368              
369             Refresh object's state.
370             Takes object as parameter.
371              
372              
373             my $emp = Emp->new(id => 10);
374             $entity_manager->refresh($emp);
375              
376             Refresh operation caches object - persitence_mangement option.
377              
378             =cut
379              
380             sub refersh {
381             my ($self, $object) = @_;
382             my $orm = $self->find_entity_mappings($object, 1);
383             $self->_reset_lazy_relation_attributes($object);
384             $self->detach($object);
385             my $entity = $self->entity($orm->entity_name);
386             my %fields_values = $orm->column_values($object);
387             my %condition_values = $entity->unique_condition_values(\%fields_values, 1);
388             my ($resultset) = $entity->find(undef, %condition_values);
389             $orm->update_object($object, $resultset);
390             $self->_manage_object($object, $resultset);
391             $orm->deserialise_eager_relation_attributes($object, $self);
392             $object;
393             }
394              
395              
396             =item insert
397              
398             Inserts object that is mapped to the entity, takes the object as parameter
399              
400              
401             my $emp = Emp->new(id => 10, name => 'scott');
402             $entity_manager->insert($emp);
403              
404              
405             =cut
406              
407             sub insert {
408             my ($self, $object, $values) = @_;
409             $values ||= {};
410             my $orm = $self->find_entity_mappings($object, 1);
411             my %fields_values = ($orm->column_values($object), %$values);
412             my $entity = $self->entity($orm->entity_name);
413             $self->_insert_to_one_relationship($entity, $object, \%fields_values, $orm);
414             $orm->run_event('before_insert', \%fields_values);
415             my $fields_values = $entity->insert(%fields_values);
416             $self->_update_generated_values($orm, $entity, $object, $fields_values);
417             my $refresh_required_flag = $entity->is_refresh_required($fields_values);
418             $self->refersh($object) if $refresh_required_flag;
419             my %unique_values = $entity->unique_condition_values($fields_values);
420             $self->_insert_to_many_relationship($entity, $object, {$entity->unique_condition_values($fields_values)}, $orm);
421             $orm->run_event('after_insert', $fields_values);
422             $self->_manage_object($object, $fields_values);
423             }
424              
425              
426             =item update
427              
428             Updates object that is mapped to the entity, takes the object as parameter
429              
430             my $emp = Emp->new(id => 10, name => 'scott');
431             $entity_manager->update($emp);
432              
433              
434             =cut
435              
436             sub update {
437             my ($self, $object, $values) = @_;
438             $values ||= {};
439             my $orm = $self->find_entity_mappings($object, 1);
440             my $entity = $self->entity($orm->entity_name);
441             $orm->deserialise_lazy_relation_attributes($object, $self);
442             $self->initialise_operation($orm->entity_name, $object);
443             my %fields_values = ($orm->column_values($object), %$values);
444             $self->_update_to_one_relationship($entity, $object, \%fields_values, $orm);
445             my $changed_column_values = $self->changed_column_values($entity, $object, \%fields_values);
446             my %unique_values = $entity->unique_condition_values(\%fields_values);
447              
448             if ($changed_column_values) {
449             $orm->run_event('before_update', \%fields_values);
450             $entity->update($changed_column_values, \%unique_values);
451             }
452             $self->_update_to_many_relationship($entity, $object, \%unique_values, $orm);
453             $self->complete_operation($orm->entity_name, $object);
454             if ($changed_column_values) {
455             $orm->run_event('after_update', \%fields_values);
456             $self->_manage_object($object, \%fields_values);
457             }
458            
459             }
460              
461              
462             =item merge
463              
464             Merges object that is mapped to the entity, takes the object as parameter
465             Is robject exists in database the updates, otherwise inserts.
466              
467              
468             my $emp = Emp->new(id => 10, name => 'scott');
469             $entity_manager->merge($emp);
470              
471              
472              
473             =cut
474              
475             sub merge {
476             my ($self, $object, $values) = @_;
477             my $orm = $self->find_entity_mappings($object, 1);
478             return if $self->has_pending_operation($orm->entity_name);
479             my $entity = $self->entity($orm->entity_name);
480             my %fields_values = $orm->unique_values($object, $entity);
481             my ($result) = $entity->find(undef, $entity->unique_condition_values(\%fields_values));
482             unless ($result) {
483             $self->insert($object, $values);
484             } else {
485             $self->_update_pk_values($orm, $entity, $object, $result)
486             unless $entity->has_primary_key_values(\%fields_values);
487             $self->update($object, $values);
488             }
489             }
490              
491              
492              
493             =item delete
494              
495             Delets object that is mapped to the entity, takes object as parameter
496              
497              
498             my $emp = Emp->new(id => 10, name => 'scott');
499             $entity_manager->delete($emp);
500              
501              
502             =cut
503              
504             sub delete {
505             my ($self, $object) = @_;
506             my $orm = $self->find_entity_mappings($object, 1);
507             return if $self->has_pending_operation($orm->entity_name);
508             $orm->deserialise_lazy_relation_attributes($object, $self);
509             $self->initialise_operation($orm->entity_name, $object);
510             my $entity = $self->entity($orm->entity_name);
511             my %fields_values = ($orm->column_values($object));
512             my %condition_values = $entity->unique_condition_values(\%fields_values);
513             $orm->run_event('before_delete', \%condition_values);
514             $self->_delete_to_many_relationship($entity, $object, \%condition_values, $orm);
515             $entity->delete(%condition_values);
516             $self->_delete_to_one_relationship($entity, $object, \%condition_values, $orm);
517             $self->complete_operation($orm->entity_name);
518             $orm->run_event('after_delete', \%condition_values);
519             $self->detach($object);
520             }
521              
522              
523             =item begin_work
524              
525             Begins a new transaction.
526              
527             $entity_manager->begin_work;
528             eval {
529             my $emp = Employee->new(name => 'foo');
530             $entity_manager->insert($user);
531             $entity_manager->commit;
532             }
533             $entity_manager->rollback if $@;
534              
535             =cut
536              
537             sub begin_work {
538             my ($self) = @_;
539             $self->connection->begin_work;
540             }
541              
542              
543             =item commit
544              
545             Commits current transaction.
546              
547             $entity_manager->commit;
548              
549             =cut
550              
551             sub commit {
552             my ($self) = @_;
553             $self->connection->commit;
554             my $persitence_mangement = $self->persitence_mangement;
555             $self->detach_all
556             if ($persitence_mangement && $persitence_mangement eq TRANSACTION_MANAGEMENT());
557             }
558              
559              
560             =item rollback
561              
562             Rollbacks current transaction.
563              
564             $entity_manager->reollback;
565              
566             =cut
567              
568             sub rollback {
569             my ($self) = @_;
570             $self->connection->rollback;
571             my $persitence_mangement = $self->persitence_mangement;
572             $self->detach_all
573             if ($persitence_mangement && $persitence_mangement eq TRANSACTION_MANAGEMENT());
574             }
575              
576              
577              
578             =item detach
579              
580             Removes database object state from cache.
581              
582             ....$entity_manager->search()
583             $entity_manager->detach
584              
585             =cut
586              
587             sub detach {
588             my ($self, $object) = @_;
589             my $persistence_cache = $self->_persistence_cache;
590             my $lazy_fetch_flags = $self->_lazy_fetch_flags;
591             delete $persistence_cache->{$object};
592             delete $lazy_fetch_flags->{$object};
593             }
594              
595              
596             =item detach_all
597              
598             Clears entity cache.
599              
600             =cut
601              
602             sub detach_all {
603             my $self = shift;
604             $self->set__persistence_cache({});
605             $self->set__lazy_fetch_flags({});
606             }
607              
608              
609             =item connection
610              
611             Returns connection object.
612              
613             =cut
614              
615             sub connection {
616             my ($self) = @_;
617             my $connection = $self->_connection;
618             unless($connection) {
619             $connection = $self->_connection(DBIx::Connection->connection($self->connection_name));
620             }
621             $connection;
622             }
623              
624              
625             =back
626              
627             =head2 PRIVATE METHODS
628              
629             =over
630              
631             =item initialise_operation
632              
633             =cut
634              
635             {
636              
637             my %pending_op;
638             sub initialise_operation {
639             my ($class, $resource, $value) = @_;
640             $value ||= 1;
641             $pending_op{$resource} = $value;
642             }
643              
644              
645             =item has_pending_operation
646              
647             =cut
648              
649             sub has_pending_operation {
650             my ($class, $resource) = @_;
651             $pending_op{$resource};
652             }
653              
654              
655             =item complete_operation
656              
657             =cut
658              
659             sub complete_operation {
660             my ($class, $resource) = @_;
661             delete $pending_op{$resource};
662             }
663             }
664              
665             =item find_entity_mappings
666              
667             Returns entity mapping object
668             Takes object or class name, and optionally
669             must_exists_validation flag that will raise an error if mapping object does not exist.
670              
671             =cut
672              
673             sub find_entity_mappings {
674             my ($self, $object, $must_exists_validation) = @_;
675             my $class_name = ref($object) || $object;
676             my $result = Persistence::ORM::mapping_meta($class_name);
677             confess "cant find entity mapping for ${class_name}"
678             if ($must_exists_validation && ! $result);
679             $result->entity_manager($self) if $result;
680             $result;
681             }
682              
683              
684             =item _update_generated_values
685              
686             Updates object by generated values.
687              
688             =cut
689              
690             sub _update_generated_values {
691             my ($self, $orm, $entity, $object, $fields_values) = @_;
692             my %value_generators = $entity->value_generators;
693             $orm->update_object($object, $fields_values, (%value_generators ? [keys %value_generators] : ()));
694             }
695              
696              
697             =item _to_many_insert_relationship
698              
699             =cut
700              
701             sub _insert_to_many_relationship {
702             my ($self, $entity, $object, $unique_values, $orm) = @_;
703             my @relations = Persistence::Relationship->insertable_to_many_relations(ref $object);
704             for my $relation (@relations) {
705             $relation->insert($orm, $entity, $unique_values, $object);
706             }
707             $orm->deserialise_eager_relation_attributes($object, $self) if @relations;
708             }
709              
710              
711             =item _insert_to_one_relationship
712              
713             =cut
714              
715             sub _insert_to_one_relationship {
716             my ($self, $entity, $object, $unique_values, $orm) = @_;
717             my @relations = Persistence::Relationship->insertable_to_one_relations(ref $object);
718             for my $relation (@relations) {
719             $relation->insert($orm, $entity, $unique_values, $object);
720             }
721             }
722              
723              
724             =item _update_pk_values
725              
726             =cut
727              
728             sub _update_pk_values {
729             my ($self, $orm, $entity, $object, $fields_values) = @_;
730             my $pk = $entity->primary_key or return;
731             $orm->update_object($object, $fields_values, $pk);
732             }
733              
734              
735             =item _update_to_many_relationship
736              
737             =cut
738              
739             sub _update_to_many_relationship {
740             my ($self, $entity, $object, $unique_values, $orm) = @_;
741             my @relations = Persistence::Relationship->updatable_to_many_relations(ref $object);
742             for my $relation (@relations) {
743             $relation->merge($orm, $entity, $unique_values, $object);
744             }
745             }
746              
747              
748             =item _update_to_one_relationship
749              
750             =cut
751              
752             sub _update_to_one_relationship {
753             my ($self, $entity, $object, $unique_values, $orm) = @_;
754             my @relations = Persistence::Relationship->updatable_to_one_relations(ref $object);
755             for my $relation (@relations) {
756             $relation->merge($orm, $entity, $unique_values, $object);
757             }
758             }
759              
760              
761             =item _delete_to_many_relationship
762              
763             =cut
764              
765             sub _delete_to_many_relationship {
766             my ($self, $entity, $object, $unique_values, $orm) = @_;
767             my @relations = Persistence::Relationship->deleteable_to_many_relations(ref $object);
768             for my $relation (@relations) {
769             $relation->delete($orm, $entity, $unique_values, $object);
770             }
771             }
772              
773              
774             =item _delete_to_one_relationship
775              
776             =cut
777              
778             sub _delete_to_one_relationship {
779             my ($self, $entity, $object, $unique_values, $orm) = @_;
780             my @relations = Persistence::Relationship->deleteable_to_one_relations(ref $object);
781             for my $relation (@relations) {
782             $relation->delete($orm, $entity, $unique_values, $object);
783             }
784             }
785              
786              
787             =item _deserialise_object
788              
789             Casts result set to passed in class name, optionally uses Object-relational mapping.
790              
791             =cut
792              
793             sub _deseralize_object {
794             my ($self, $class_name, $resultset, $entity) = @_;
795             my $result;
796             my $orm = $self->find_entity_mappings($class_name);
797             if($orm) {
798             $result = $orm->deserialise($resultset, $self);
799             } else {
800             my $meta = eval { $class_name->can('meta') ? $class_name->meta : undef };
801             if ($meta) {
802             my $attributes = $meta->all_attributes;
803             $result = {map {($_->name, $resultset->{$_->name} )} @$attributes};
804             } else {
805             $result = {%$resultset};
806             }
807             }
808             if ($class_name) {
809             $self->_manage_object($result, $resultset) ;
810             $self->_reset_lazy_relation_attributes($result);
811             }
812             $result;
813             }
814              
815              
816             =item changed_column_values
817              
818             Returns hash ref of fields_values that have been changed.
819              
820             =cut
821              
822             sub changed_column_values {
823             my ($self, $entity, $object, $fields) = @_;
824             my $result;
825             if ($self->persitence_mangement) {
826             my $persistence_cache = $self->_persistence_cache;
827             my $record = $persistence_cache->{$object};
828             if ($record) {
829             my $lobs = $entity->lobs;
830             my @columns = ($entity->updatable_columns,($lobs ? values %$lobs : ()));
831             for my $column (@columns) {
832             my $column_name = $column->name;
833             next unless exists $fields->{$column_name};
834             if(($fields->{$column_name} || '') ne ($record->{$column_name} || '')) {
835             $result->{$column_name} = $fields->{$column_name};
836             $fields->{$column_name} = $record->{$column_name};
837             }
838             }
839             return $result;
840             }
841             }
842             $fields;
843             }
844              
845              
846             =item _manage_object
847              
848             Creates database state of the object in the persistence cache.
849             Takes object, resultset as parameters.
850              
851             =cut
852              
853             sub _manage_object {
854             my ($self, $object, $resultset) = @_;
855             my $persistence_cache = $self->_persistence_cache;
856             if ($self->persitence_mangement) {
857             $persistence_cache->{$object} = {%$resultset};
858             }
859             }
860              
861              
862              
863             =item add_lazy_fetch_flag
864              
865             Adds lazy flag.
866             Takes object and attirubte for lazy retrieval.
867              
868             =cut
869              
870             sub add_lazy_fetch_flag {
871             my ($self, $object, $attribute) = @_;
872             my $fetch_flags = $self->_lazy_fetch_flags;
873             my $attributes = $fetch_flags->{$object} ||= {};
874             $attributes->{$attribute} = 1;
875             }
876              
877              
878             =item has_lazy_fetch_flag
879              
880             Returns true if passed in object has lazy flag for passed in attribute.
881              
882             =cut
883              
884             sub has_lazy_fetch_flag {
885             my ($self, $object, $attribute) = @_;
886             my $fetch_flags = $self->_lazy_fetch_flag($object);
887             $fetch_flags ||= {};
888             $fetch_flags->{$attribute};
889             }
890              
891              
892             =item _reset_lazy_relation_attributes
893              
894             =cut
895              
896             sub _reset_lazy_relation_attributes {
897             my ($self, $object) = @_;
898             my $fetch_flags = $self->_lazy_fetch_flags;
899             my $attributes = $fetch_flags->{$object} ||= {};
900             for my $attribute (keys %$attributes) {
901             my $call = "reset_$attribute";
902             $object->$call;
903             }
904             $fetch_flags->{$object} = {};
905             }
906              
907              
908             1;
909              
910             __END__