Featured image of post 第5回-忘れないように保存しよう — URL短縮サポーターを作ってみよう

第5回-忘れないように保存しよう — URL短縮サポーターを作ってみよう

サーバー再起動でデータが消えないよう、SQLiteデータベースで永続化します。DBIを使ったデータベース接続の基本を学びましょう。

@nqounetです。

連載「URL短縮サポーターを作ってみよう」の第5回です。

前回の振り返り

第4回では、Digest::SHAを使ってURLから短縮コードを生成する方法を学びました。

前回学んだ内容を簡単に振り返ります。

  • use Digest::SHA qw(sha1_hex);でSHA-1ハッシュ関数を使えるようにした
  • substr(sha1_hex($url), 0, 6)で先頭6文字の短縮コードを生成した
  • Perlのハッシュ変数%urlsにURLとコードの対応を保存した(仮実装)

今回は、サーバーを再起動してもデータが消えないよう、データベースを導入します。

今回のゴール

第5回では、以下を達成することを目標とします。

  • データの永続化が必要な理由を理解する
  • DBIモジュールの役割を知る
  • SQLiteデータベースに接続する方法を学ぶ

サーバー再起動したら消えちゃう!

タカシさんの問題

前回、短縮コードの生成が動くようになり、タカシさんは喜んでいました。しかし翌日、タカシさんから連絡がありました。

「昨日登録したURLが全部消えてる!」

これは前回触れた「現状の制限」が原因です。Perlのハッシュ変数%urlsはメモリ上にしか存在しないため、サーバーを停止すると内容はすべて失われてしまいます。

永続化の必要性

Webアプリケーションでデータを保持し続けるには、永続化(persistence)が必要です。永続化とは、プログラムが終了してもデータが残るようにすることです。

永続化の方法はいくつかあります。

  • ファイルに書き出す
  • データベースに保存する
  • 外部ストレージサービスを利用する

今回は、データベースを使った永続化を選択します。データベースを使えば、データの検索や管理が簡単になり、将来的な機能拡張にも対応しやすくなります。

なぜSQLiteなのか

データベースにもMySQL、PostgreSQL、SQLiteなど様々な種類があります。今回はSQLiteを採用します。理由は以下のとおりです。

  • サーバーの設定が不要(ファイル1つで動作する)
  • インストールが簡単
  • 小規模なアプリケーションには十分な性能

SQLiteはデータベースの内容を単一のファイルに保存します。そのため、設定ファイルやサーバープロセスを別途用意する必要がありません。個人用のURL短縮サービスには最適な選択です。

DBIでデータベースに接続しよう

DBIとは

PerlでデータベースにアクセスするにはDBIモジュールを使います。DBIはDatabase Interfaceの略で、様々なデータベースに統一されたインターフェースでアクセスできるモジュールです。

DBIを使うと、MySQLでもPostgreSQLでもSQLiteでも、ほぼ同じコードでデータベースを操作できます。データベースの種類ごとの違いは、DBD(Database Driver)モジュールが吸収してくれます。

今回はSQLiteを使うので、DBIに加えてDBD::SQLiteモジュールも必要です。

モジュールをインストールする

DBIとDBD::SQLiteをインストールします。ターミナルで以下のコマンドを実行してください。

1
cpanm DBI DBD::SQLite

データベースに接続する

DBIを使ってSQLiteデータベースに接続するコードを見てみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#!/usr/bin/env perl
# connect_db.pl
# Perl: 5.10以上
# 依存: DBI, DBD::SQLite(cpanmでインストール)
use strict;
use warnings;
use DBI;

my $dbh = DBI->connect(
    "dbi:SQLite:dbname=urls.db",
    "",
    "",
    { RaiseError => 1, AutoCommit => 1 }
);

print "データベースに接続しました!\n";

このコードがデータベース接続の基本形です。各部分を詳しく解説します。

use DBI;

1
use DBI;

DBIモジュールを読み込みます。これでデータベース操作に必要な関数やメソッドが使えるようになります。

DBI->connect()

1
2
3
4
5
6
my $dbh = DBI->connect(
    "dbi:SQLite:dbname=urls.db",
    "",
    "",
    { RaiseError => 1, AutoCommit => 1 }
);

DBI->connect()はデータベースへの接続を確立し、データベースハンドル($dbh)を返します。引数は4つあります。

第1引数(データソース名)

"dbi:SQLite:dbname=urls.db"

この文字列はDSN(Data Source Name)と呼ばれ、3つの部分で構成されています。

  • dbi: DBIを使うことを示す固定のプレフィックス
  • SQLite: 使用するデータベースドライバ(DBD::SQLiteを使用)
  • dbname=urls.db: データベースファイルのパス

このコードを実行すると、カレントディレクトリにurls.dbというファイルが作成されます。このファイルがSQLiteデータベースの実体です。

第2引数・第3引数(ユーザー名・パスワード)

1
2
"",
"",

SQLiteはファイルベースのデータベースなので、ユーザー認証の仕組みがありません。そのため、ユーザー名とパスワードは空文字列を指定します。

MySQL等のサーバー型データベースを使う場合は、ここに適切な認証情報を設定します。

第4引数(オプション)

1
{ RaiseError => 1, AutoCommit => 1 }

接続オプションをハッシュリファレンスで指定します。

  • RaiseError => 1: エラー発生時に例外を投げる。これを設定しておくと、エラーを見逃さずに済む
  • AutoCommit => 1: 各SQL文を自動的にコミットする。トランザクションを手動で管理しない場合はこの設定が便利

接続を確認して切断する

接続が成功したかを確認し、使い終わったら切断するコードを見てみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env perl
# connect_and_disconnect.pl
# Perl: 5.10以上
# 依存: DBI, DBD::SQLite(cpanmでインストール)
use strict;
use warnings;
use DBI;

my $dbh = DBI->connect(
    "dbi:SQLite:dbname=urls.db",
    "",
    "",
    { RaiseError => 1, AutoCommit => 1 }
);

if ($dbh) {
    print "接続成功!\n";
    print "SQLiteバージョン: " . $dbh->{sqlite_version} . "\n";
} else {
    die "接続失敗: $DBI::errstr\n";
}

$dbh->disconnect;
print "切断しました。\n";

コードの各部分を解説します。

接続の確認

1
2
3
4
if ($dbh) {
    print "接続成功!\n";
    print "SQLiteバージョン: " . $dbh->{sqlite_version} . "\n";
}

DBI->connect()が成功すると、データベースハンドル($dbh)が返されます。このハンドルは真の値なので、if ($dbh)で接続成功を確認できます。

$dbh->{sqlite_version}はDBD::SQLite固有の属性で、使用しているSQLiteのバージョンを取得できます。接続が正しく行われているかの確認に便利です。

エラー処理

1
2
3
} else {
    die "接続失敗: $DBI::errstr\n";
}

接続に失敗した場合、$DBI::errstrにエラーメッセージが格納されています。今回はRaiseError => 1を設定しているため、実際にはエラー時に自動的に例外が投げられますが、明示的なエラー処理も書いておくと安心です。

切断

1
$dbh->disconnect;

データベースとの接続を明示的に切断します。Perlのスクリプトが終了すると自動的に切断されますが、明示的に切断する習慣をつけておくと良いでしょう。

動作確認

スクリプトを実行する

上記のコードをconnect_and_disconnect.plとして保存し、ターミナルで実行してください。

1
perl connect_and_disconnect.pl

以下のような出力が表示されれば成功です。

1
2
3
接続成功!
SQLiteバージョン: 3.xx.x
切断しました。

バージョン番号は環境によって異なります。

データベースファイルの確認

スクリプトを実行後、カレントディレクトリにurls.dbというファイルが作成されていることを確認してください。

1
ls -la urls.db

このファイルがSQLiteデータベースの実体です。サーバーを再起動しても、このファイルが残っている限りデータは失われません。これで永続化の第一歩が完了しました。

まとめ

今回学んだこと

第5回では、以下のことを学びました。

  • メモリ上のデータはサーバー再起動で消えるため、永続化が必要である
  • PerlでデータベースにアクセスするにはDBIモジュールを使う
  • DBI->connect("dbi:SQLite:dbname=urls.db", "", "", { RaiseError => 1, AutoCommit => 1 })でSQLiteに接続できる
  • $dbh->disconnectで接続を切断する

次回予告

次回は「データの住所を決めよう — テーブル設計」をテーマに、URLを保存するためのテーブル構造を設計します。CREATE TABLE文を使って、id、original_url、short_code、created_atといったカラムを定義していきます。お楽しみに。

comments powered by Disqus
Hugo で構築されています。
テーマ StackJimmy によって設計されています。