블로그 이미지
JEEN

서울에 사는 꽃청년의 IT찌질모험기

Rss feed Tistory
IT/Perl 2008.08.06 14:22

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #3 - Component

  이번에는 Component 에 대해서 알아보겠습니다. 일단 예제부터 보고 시작하죠.

  Mytest/Company.pm 을 열어봅니다.

package MyTest::Company;

use strict;
use warnings;

use base 'DBIx::Class';
use AutoStoreDateTime;

__PACKAGE__->load_components("PK::Auto", "+AutoStoreDateTime", "Core");
__PACKAGE__->table("company");
__PACKAGE__->add_columns(
  "company_id",
  { data_type => "INT", default_value => undef, is_nullable => 0, size => 11 },
  "name",
  { data_type => "VARCHAR", default_value => "", is_nullable => 0, size => 255 },
  "created_on",
  { data_type => "DATETIME", default_value => "", is_nullable => 0, size => 19 },
  "updated_on",
  { data_type => "DATETIME", default_value => "", is_nullable => 0, size => 19 },
);
__PACKAGE__->set_primary_key("company_id");


# Created by DBIx::Class::Schema::Loader v0.04005 @ 2008-08-05 16:39:27                      
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:DHRIea3OvvtGG+yhaBVTvQ                        


# You can replace this text with custom content, and it will be preserved on regeneration    
1;

 이 중에서 제가 살짝 추가한 부분이 있습니다.

use AutoStoreDateTime;
__PACKAGE__->load_components("PK::Auto", "+AutoStoreDateTime", "Core");

 바로 이부분에 PK::Auto 라는 component 도 불러오라고 지정했습니다. PK::Auto 는 온라인 게임에서 자동으로 PK 를 수행하는   Primary Key Auto Increment 라고 보시면 됩니다. 즉 이 Schema Class 에서는 company_id 가 Primary Key 이니까 자동으로 Auto Increment 해준다는 거죠. (물론 SQL 에서 Auto Increment 를 지정해주면 DBMS 자체적으로 이 행위를 수행하지만, auto increment 가 지정되지 않은 경우에는 PK::Auto가 알아서 해줍니다. 이것을 확인하기 위해서 직접 Company 테이블을 변경해보시길 바랍니다)

  그리고 AutoStoreDateTime 도 있습니다. 근데 이 앞에 +라고 붙었는데.. 이것은 Custom component 입니다. PK::Auto 같은 경우는 DBIx::Class::PK::Auto 라는 모듈을 불러오는 것인데, AutoStoreDateTime 은 DBIC 정식 모듈이 아닌... 여기서 만들어서 쓰겠다라는 것이죠.
use AutoStoreDateTime;

use strict;
use warnings;
use base 'DBIx::Class';

use DateTime;

sub insert {
    my $self = shift;
   
    $self->created_on( DateTime->now( time_zone => 'Asia/Seoul' ) )
                             if $self->result_source->has_column('created_on');
                      
    $self->next::method(@_);
}

sub update {
    my $self = shift;

    $self->updated_on( DateTime->now( time_zone => 'Asia/Seoul' ) )
                           if $self->result_source->has_column('updated_on');
    $self->next::method(@_);
}

1;

  이와 같은 컴포넌트 모듈을 만들었습니다. 이것을 AutoStoreDateTime.pm 이라고 저장하고 MyTest.pm 과 같은 디렉토리에 놓습니다.
  그럼 어떤 결과를 보이는 지 확인해 볼까요?
my $company = $schema->resultset('Company');

while(<DATA>) {
    chomp;
    $company->create({
        'name'    => $_,
    });
}

__DATA__
I company
N company
D company
E company
A company
Y company

  이렇게 Company.name 을 만들도록합니다. company_id 도 지정하지 않았고, created_on 도 지정하지 않았습니다. 등록날짜도 모르면 어떻게 하려고 이럴까요?
사용자 삽입 이미지
  하지만 이렇게 created_on 은 create 한 시점의 날짜/시간을 가지고 있습니다. company_id 도 물론 지정하지 않았는데 이렇게 생겼네요(SQL에서 auto increment 가 있으면 뭐 그게 그거입니다만).

 근데 사장 마인드를 가지신 saillinux 님께서 짝수 회사번호를 가진 회사는 전부 소문자로 표기하고 싶다는 얼토당토 않은 요구를 하고 있습니다. 어쩔 수 있나요. 까라면 까야지..

my $company = $schema->resultset('Company')->search({});

while(my $row = $company->next) {
    if ($row->company_id % 2 == 0) {
        $row->name(lcfirst $row->name);
        $row->update;
    }
}

  이렇게 하면 되겠죠?
사용자 삽입 이미지
  그러면 update 된 레코드만 updated_on 이 지정되게 되죠.  어때요? 참 쉽죠?

 이렇게 DBIC 의 Component 활용에 대해서 알아보았습니다. :-) 직접 Component 를 만들어서 보다 편하게 DB 를 주물러 보심은 어떠실런지요?

  다음에는 Relation 에 대해서 살짝 알아보겠습니다. 

* 참고
 - **** Project



신고
IT/Perl 2008.08.05 20:15

[ Perl ] Perl 에서의 ORM , DBIx::Class에 대해서... #2 - DBIC 의 간단한 사용


  그럼, DBIC::Schema::Loader 로 만든 Schema Class 는 어떻게 사용하는 것일까요?

use strict;
use warnings;
use MyTest;  # 앞서 정의한 Schema Class
use DateTime;

my $schema = MyTest->connect(
    'dbi:mysql:mytest',
    'root',
    'PASSWORD');  # DBI 의 connect_info 랑 같습니다.

my $user = $schema->resultset('User');

while(<DATA>) {
    chomp;
    my @data = split /,/, $_;
    $user->create({
        'user_id' => $data[0],
        'name'    => $data[1],
        'created_on' => $dt->ymd. ' '. $dt->hms,
    });  # INSERT INTO..
}

__DATA__
1,JEEN
2,saillinux
3,하얀_고양이
4,a3r0
5,yuni
6,keedi
7,pung96
8,song
9,ssie
10,amorette

  이 스크립트를 MyTest.pm 과 같은 장소에 놓으시고... 적당한 이름으로 저장해서 실행해봅니다.
  아무것도 안나올겁니다. 그렇다면... DB 를 확인해볼까요?
사용자 삽입 이미지
이렇게 제대로 들어가 있네요 :-)
그러면 이렇게 입력된 데이터를 가지고 놀아 볼까요?

use strict;
use warnings;
use MyTest;
use DateTime;

my $schema = MyTest->connect(
    'dbi:mysql:mytest',
    'root',
    'PASSWORD');

my $user = $schema->resultset('User')->search({
    'user_id' => { '<' => 5 },
});  # SELECT * FROM user WHERE user_id < 5;

while(my $row = $user->next) {
 print $row->name."\n";
}
 위의 주석처럼 user_id 가 5보다 작은 사람들을 불러모읍니다. :-)
 JEEN
 saillinux
 하얀_고양이
 a3r0
 결과는 이처럼 나오겠죠?
 
  ->search 로 데이터를 줏어올 때는 기본적으로 복수로 가정합니다. 그러니 $user->next 같은 것으로 루프를 돌려주는 것입니다. $user->all 같은 것을 사용하면 말 그대로 전체 데이터를 ARRAY 로 받습니다.

 여기에서 생각난 예제:
 근데 전 하얀_고양이 님을 별로 좋아하지 않습니다. 그래서 지워버리고 싶어요.

use utf8;

my $user = $schema->resultset('User')->find({
    'name' => '하얀_고양이',
});    # find 를 사용할 경우 하나의 레코드만을 얻어옵니다.

print $user->name;
$user->delete;
 
  혹은
use utf8;
my $user = $schema->resultset('User')->search({});

while(my $row = $user->next) {
  $row->delete if $row->name eq '하얀_고양이';  # 이렇게도 삭제할 수 있죠 :-)
}

  이렇게 해서 하얀_고양이님을 지웠습니다.
  그러니 IRC #perl 에 계신 분들이 모두 기뻐하셔서 빵글이를 붙이고 싶다는 데요. :-)
  그럼 어떻게 할까요?
my $user = $schema->resultset('User')->search({});

while(my $row = $user->next) {
    $row->name($row->name . '_^^');
    $row->update;
}
 
사용자 삽입 이미지

 과연.. 모두들 기뻐하시는 군요 :-)

 이런식으로 직감적으로 DB의 데이터를 조작할 수 있는 것이 바로 DBIC 의 강점입니다.
 이에관한 예제는 DBIx::Class 페이지에서 쉽게 찾아볼 수 있고, 보다 다양한 예제를 제공해줍니다.
  그리고 보다 자세한 SELECT 구문에 대한 예제는 앞으로도 계속 적어나가도록 하겠습니다.

  다음번에는 Component 에 대해서 간단하게 알아보겠습니다. 

신고
TOTAL 462,404 TODAY 31

티스토리 툴바