Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Re: How can I avoid creating two instances of the same object

by mattr (Curate)
on Mar 02, 2006 at 16:15 UTC ( [id://533950]=note: print w/replies, xml ) Need Help??


in reply to How can I avoid creating two instances of the same object

Hello,
It seems you have it slightly backwards from where I sit, since I would expect that User->new would return a new instance of a User object.
  my $newuser = User->new({name="matt"});
You should only make one database connection when your app runs and then everything uses that. The new method of each object should not be creating a new database handle. With Class::DBI anyway you wouldn't. Making a new object does not make a new database handle, it just points to the one you were using.

You don't have to use Class::DBI as mentioned above, (i.e. you could just use DBI in the parent object) but that would be my way of doing it. For example you have WebApp::DBI (which is use base 'Class::DBI'). Then WebApp::User and WebApp::Company are both use base 'WebApp::DBI'. In WebApp::DBI I have a getdbh subroutine so all classes and objects inherit a ->getdbh method.

package WebApp::DBI; use base 'Class::DBI'; use DBD::mysql; use Site; # where I store db account info WebApp::DBI->set_db('Main', "DBI:mysql:database=$dbname;host=$hostname;port=$port", $dbusername, $dbpassword); # you can say __PACKAGE__ instead of "WebApp::DBI" WebApp::DBI->add_constructor(all_reverse_by_id => '1=1 ORDER BY id DESC'); # a query inherited by all objects sub getdbh { # so we don't have to set up our own # db_Main subroutine that would return a dbh my @dbhandles = WebApp::DBI->db_handles; # I use Ima::DBI->db_handles which Class::DBI # inherits instead of making a sub db_Main # as Class::DBI suggests, I'm wierd. my $dbh = $dbhandles[0]; $dbh->{RaiseError} = 1; return $dbh; } 1;

With this approach I believe you only need to use an object in a subroutine that needs it, otherwise the module is not loaded. Also objects inheriting from Class::DBI load columns lazily based on definitions of Essential columns.

Also note that you can put generic retrieval code in the parent module (or in that parent's parent as with Class::DBI which provides the retrieve method) and then just do special cases in the child modules.

Hope this helps. So bottom line is, for all this to be easily cleared up why not read the Class::DBI perldoc a few times and as rhesa notes you can get the db handle from its connection method or better yet as they recommend override db_Main with your own settings.

Replies are listed 'Best First'.
Re^2: How can I avoid creating two instances of the same object
by rhesa (Vicar) on Mar 02, 2006 at 16:25 UTC
    Not to detract from your post, but Class::DBI already gives you db_Main for free. Your getdbh == WebApp::DBI->db_Main.
      Thanks you are correct and posted just as I was adding an explanation ("I'm wierd"). This is old code of mine, for some reason that seemed good at the time, but I don't remember instead of overriding db_Main I pulled it from Ima::DBI. I wonder why I did that.. put another way what other db handles would be in that array I wonder.
        Thank you all for your advice and for your help. I figured out how to get this done! Here is my final working code. I am loading my @ISA in the beginning with each of my packages and I am requiring the package in a method using an eval statement. It looks a little wierd but it works. I'll get a better benchmark of the speed when I get a good prototype working. Here is my calling script and the relevant methods.
        use Data::Dumper; use CBIDatabase; my $dbh = CBIDatabase->new(); $dbh->load_package('Company'); my %company; $company{'id'} = '03459875437'; my $ref = $dbh->Company::client(\%company,'*',); print "\n\nAsking for all matching table info:\n"; print Dumper($ref);
        Here is the load_package method of the CBIDatabase class
        use strict; use DBI; my @ISA = qw(Company); sub load_package { my $self = shift; my $package = shift; require eval{$package.'.pm'}; } sub new { ## database stuff here }
        I'm excited! This seems to work very well. I don't like to use eval statements but I think I'll have to if I want to require the modules dynamically. Again thanks for all of the help. This is a very old database that didn't follow any of the rules, that class::dbi seemed to need.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://533950]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (4)
As of 2024-04-25 16:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found