line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Dao::Map::Helper;
|
2
|
|
|
|
|
|
|
#use warnings;
|
3
|
1
|
|
|
1
|
|
34642
|
use strict;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
42
|
|
4
|
1
|
|
|
1
|
|
3102
|
use DBI;
|
|
1
|
|
|
|
|
28593
|
|
|
1
|
|
|
|
|
84
|
|
5
|
1
|
|
|
1
|
|
564
|
use DBD::mysql;
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use Error qw{:try};
|
7
|
|
|
|
|
|
|
use Getopt::Long;
|
8
|
|
|
|
|
|
|
use Pod::Usage;
|
9
|
|
|
|
|
|
|
use Carp;
|
10
|
|
|
|
|
|
|
our @ISA = qw(Exporter);
|
11
|
|
|
|
|
|
|
our @EXPORT = qw(
|
12
|
|
|
|
|
|
|
);
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Dao::Map::Helper - Simplify the creation of DAO (Data Access Objects). Kind of a low level ORM, where you can still use SQL and then map the result set to the class objects.
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 VERSION
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
Version 0.04
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=cut
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our $VERSION = '0.04';
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
Simplify the creation of Dao classes and the mapping between relational table and class.
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
dao-map-helper --dsn=dbi:mysql:mydb:localhost:3306 --user=root --pwd=pwd --package=package
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 Description
|
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
You might have seen helper scripts which are part of Catalyst Devel framework.
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
The helper scripts create the inital structure based on which you can continue your work.
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
What does Dao::Map::Helper do?
|
39
|
|
|
|
|
|
|
The Dao::Map::Helper can be invoked via command line and inturn it will create .pm files that are also called Value Objects.
|
40
|
|
|
|
|
|
|
These are just class files with attributes in them.
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
Where do i use it?
|
43
|
|
|
|
|
|
|
Every time you fetch a result set from the database using DBI module like
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
...
|
46
|
|
|
|
|
|
|
$sth = $dbh->prepare("select * from user");
|
47
|
|
|
|
|
|
|
$sth->execute();
|
48
|
|
|
|
|
|
|
while ($row = $sth->fetchrow_hashref() ) {
|
49
|
|
|
|
|
|
|
push(@user_arry2,$row);
|
50
|
|
|
|
|
|
|
}
|
51
|
|
|
|
|
|
|
...
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
Template toolkit file would look like:
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
...
|
56
|
|
|
|
|
|
|
[% FOREACH user IN user_arry %]
|
57
|
|
|
|
|
|
|
[% user.id %] : [% user.username %]
|
58
|
|
|
|
|
|
|
[% END %]
|
59
|
|
|
|
|
|
|
...
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
With the above approach if the database layer changes then you would have to search every view where the column name is used and change it. Instead if you had a interface. A change in a single file is all that is needed. In the above approach since you are directly passing the database hash values the impact of a change is propogated across your website, making it hard to maintain.
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
The new approach would be
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
...
|
68
|
|
|
|
|
|
|
$sth = $dbh->prepare("select * from user");
|
69
|
|
|
|
|
|
|
$sth->execute();
|
70
|
|
|
|
|
|
|
while ($row = $sth->fetchrow_hashref() ) {
|
71
|
|
|
|
|
|
|
my $user_obj = web_app::Vo::UserVo->new($row);
|
72
|
|
|
|
|
|
|
push(@user_arry,$user_obj);
|
73
|
|
|
|
|
|
|
}
|
74
|
|
|
|
|
|
|
...
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
This way you get to create a mapping class that you can change if there is a change.
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
The mapping file looks like this:
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
package MyApp::Vo::userVo;
|
82
|
|
|
|
|
|
|
use strict;
|
83
|
|
|
|
|
|
|
use warnings;
|
84
|
|
|
|
|
|
|
sub new {
|
85
|
|
|
|
|
|
|
shift;
|
86
|
|
|
|
|
|
|
my($row) = @_;
|
87
|
|
|
|
|
|
|
my $self = {};
|
88
|
|
|
|
|
|
|
$self->{status}=$row->{status} || "";
|
89
|
|
|
|
|
|
|
$self->{updated_by}=$row->{updated_by} || "";
|
90
|
|
|
|
|
|
|
$self->{created_date}=$row->{created_date} || "";
|
91
|
|
|
|
|
|
|
$self->{username}=$row->{username} || "";
|
92
|
|
|
|
|
|
|
$self->{email}=$row->{email} || "";
|
93
|
|
|
|
|
|
|
$self->{password}=$row->{password} || "";
|
94
|
|
|
|
|
|
|
$self->{updated_date}=$row->{updated_date} || "";
|
95
|
|
|
|
|
|
|
$self->{id}=$row->{id} || "";
|
96
|
|
|
|
|
|
|
$self->{created_by}=$row->{created_by} || "";
|
97
|
|
|
|
|
|
|
bless($self);
|
98
|
|
|
|
|
|
|
return $self;
|
99
|
|
|
|
|
|
|
}
|
100
|
|
|
|
|
|
|
return 1;
|
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
So if the username in the database changes to 'user_name' you dont have to modify every template view where it is used. You just need to change this mapping file.
|
103
|
|
|
|
|
|
|
Also the mapping between the database and class attributes happens in this class. So it's kind of a low level ORM, where you can still use SQL and then map the result set to the class objects.
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
How do i create the mapping file?
|
106
|
|
|
|
|
|
|
If your database has say 20 tables, creating a mapping file similar to the one above is tedious task. Instead you can use the Dao::Map::Helper module which will create these classes for you. Just copy them over to the right folder and start using.
|
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
What is the command i need to run?
|
109
|
|
|
|
|
|
|
After you install Dao::Map::Helper the helper script is available in the command line.
|
110
|
|
|
|
|
|
|
You can run the following command in the directory you want the .pm files to be present in.
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
Examples:
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
dao-map-helper --dsn=dbi:mysql:mydb:localhost:3306 --user=root --pwd=pwd --package=package
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
What are the dependencies and limitations?
|
117
|
|
|
|
|
|
|
As of now it just works with mysql.
|
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=cut
|
120
|
|
|
|
|
|
|
##################################################################################################
|
121
|
|
|
|
|
|
|
sub Main{
|
122
|
|
|
|
|
|
|
pod2usage(2) unless @ARGV;
|
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
my ($dsn,$user,$pwd,$package);
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
GetOptions(
|
128
|
|
|
|
|
|
|
'dsn=s' => \$dsn,
|
129
|
|
|
|
|
|
|
'user=s' => \$user,
|
130
|
|
|
|
|
|
|
'pwd=s' => \$pwd,
|
131
|
|
|
|
|
|
|
'package=s' => \$package
|
132
|
|
|
|
|
|
|
) || pod2usage(2);
|
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
if (@ARGV) {
|
135
|
|
|
|
|
|
|
pod2usage(
|
136
|
|
|
|
|
|
|
-msg => "Unparseable arguments received: " . join(',', @ARGV),
|
137
|
|
|
|
|
|
|
-exitval => 2,
|
138
|
|
|
|
|
|
|
);
|
139
|
|
|
|
|
|
|
}
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
create_dao($dsn,$user,$pwd,$package);
|
142
|
|
|
|
|
|
|
print "\nFinished!\n";
|
143
|
|
|
|
|
|
|
}
|
144
|
|
|
|
|
|
|
##################################################################################################
|
145
|
|
|
|
|
|
|
sub create_dao{
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
my ($dsn,$user,$pwd,$package) = @_;
|
148
|
|
|
|
|
|
|
my $dbh = DBI->connect( $dsn , $user, $pwd ) || croak("Unable to connect: $DBI::errstr\n");
|
149
|
|
|
|
|
|
|
try{
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
my $sth1;
|
152
|
|
|
|
|
|
|
$sth1 = $dbh->table_info();
|
153
|
|
|
|
|
|
|
my $table_info = $sth1->fetchall_hashref('TABLE_NAME');
|
154
|
|
|
|
|
|
|
foreach my $table_name ( keys %$table_info )
|
155
|
|
|
|
|
|
|
{
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
my $sth2 = $dbh->column_info(undef, undef, $table_name, undef);
|
158
|
|
|
|
|
|
|
my $col_info = $sth2->fetchall_hashref('COLUMN_NAME');
|
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
$table_name = ucfirst($table_name);
|
161
|
|
|
|
|
|
|
print "use " . $package . "::Vo::$table_name"."_Vo;" . "\n";
|
162
|
|
|
|
|
|
|
open(FILE,">$table_name"."_Vo.pm");
|
163
|
|
|
|
|
|
|
print FILE "package ". $package . "::Vo::".$table_name."_Vo;\n";
|
164
|
|
|
|
|
|
|
print FILE "use strict;\n";
|
165
|
|
|
|
|
|
|
print FILE "use warnings;\n";
|
166
|
|
|
|
|
|
|
print FILE "sub new {\n";
|
167
|
|
|
|
|
|
|
print FILE "\tshift;\n";
|
168
|
|
|
|
|
|
|
print FILE "\tmy(\$row) = \@_;\n";
|
169
|
|
|
|
|
|
|
print FILE "\tmy \$self = {};\n";
|
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
foreach my $column_name ( keys %$col_info )
|
172
|
|
|
|
|
|
|
{
|
173
|
|
|
|
|
|
|
print FILE "\t\$self->{$column_name}=\$row->{$column_name} || \"\";\n";
|
174
|
|
|
|
|
|
|
}
|
175
|
|
|
|
|
|
|
$sth2->finish();
|
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
print FILE "\tbless(\$self);\n";
|
178
|
|
|
|
|
|
|
print FILE "\treturn \$self;\n";
|
179
|
|
|
|
|
|
|
print FILE "}\n";
|
180
|
|
|
|
|
|
|
print FILE "return 1;";
|
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
close(FILE);
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
$sth1->finish();
|
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
}
|
188
|
|
|
|
|
|
|
catch Error with {
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
}
|
191
|
|
|
|
|
|
|
finally{
|
192
|
|
|
|
|
|
|
$dbh->disconnect();
|
193
|
|
|
|
|
|
|
};
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
##################################################################################################
|
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
=head1 AUTHOR
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Arjun Surendra, C<< >>
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=head1 BUGS
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
Please report any bugs or feature requests to C, or through
|
204
|
|
|
|
|
|
|
the web interface at L. I will be notified, and then you'll
|
205
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes.
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=head1 SUPPORT
|
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command.
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
perldoc Dao::Map::Helper
|
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
You can also look for information at:
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=over 4
|
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
L
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
L
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=item * CPAN Ratings
|
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
L
|
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=item * Search CPAN
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
L
|
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=back
|
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS
|
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Like to thank Rajesh and Venky for reviewing the code.
|
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
Copyright 2011 Arjun Surendra.
|
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it
|
246
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published
|
247
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License.
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information.
|
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=cut
|
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
1;
|
255
|
|
|
|
|
|
|
# End of Dao::Map::Helper
|