従業員の検索(select文の使用)

画面を表示した瞬間、または登録/更新/削除のオペレーションが完了した際、従業員テーブルから全てのデータを検索し、再表示している。

検索に関するコードは以下のようになっている。

function searchEmployees() {
   // selectクエリの発行
   var rs = db.execute("select * from employee order by id");

   ...(中略)...

   try {
      // ResultSet#isValidRow()メソッドがtrueを返す間ループ
      while (rs.isValidRow()) {

         ...(中略)...

         rs.next();
      }
   } finally {
      if (rs) rs.close();
   }
}

employeeテーブルから、idの昇順で従業員データを検索し、ループしながら一覧表を作成している。

ResultSetクラスのメソッドを使用して検索結果を処理し、最後にクローズする必要がある、というのが重要な点だ。

従業員の登録(insert文の使用)

画面上部のテキストフィールドに入力し、「登録」ボタンを押すとinsert文が発行されて従業員テーブルに行が追加される。それを行っているのは以下の部分だ。

function createEmployee() {

   // テキストフィールドに文字が入力されていれば、
   // insert処理を行う
   var nameField = document.getElementById("name");
   var employeeName = nameField.value;
   if (employeeName.length > 0)
      // insert文の発行
      db.execute("insert into employee (name) values (?)", [employeeName]);

   // 一覧の再検索
   searchEmployees();
   nameField.value = ""; // テキストフィールドのクリア
}

Database#executeメソッドを用いて、insert文を発行している個所に注目。「?」によるプレースホルダを用いており、第二引数にそのプレースホルダを置き換えるための引数を指定している。引数は一つでも配列に格納する([]で囲んでいる)必要がある。

従業員の更新、削除(update文、delete文の使用)

更新、削除に関しては、今までの解説と重複するので詳しくは触れない。SQLを実行している部分は以下のようなコードになっている。

update文を発行している個所:

db.execute("update employee set name = ? where id = ?", [employeeName, selectedEmployeeId]);

delete文を発行している個所:

db.execute("delete from employee where id = ?", [selectedEmployeeId]);

高機能デバッガは必須

以上で、Gearsのデータベース機能の解説は終わりだ。

ブラウザ + Gearsのみで、かなり本格的なアプリケーションを作成可能なことがおわかりいただけただろうか。

ただ、今回サンプルを作成してみて思ったことは、やはりJavaScriptによるコーディングはデバッグが容易ではないということ。特に、Gearsはβ版ということもあってエラーメッセージなどがまだまだ洗練されていない。Firebugなどの高機能JavaScriptデバッガは必須だ(Firebugについてはこちらの記事が詳しい)。

最後に、今回使用したサンプルを実行する方法を示しておく。

Gearsを使用したアプリケーションは、<script>タグを用いてgears_init.jsというJavaScripファイルを読み込む必要があるのは説明したとおりだ。

サンプルを実行するには、こちらのページの「Get gears_init.js」というリンクから、gears_init.jsをダウンロードして保存しておく必要がある。

以下に示すサンプル全文をコピー&ペーストしたものを「employee.html」という名前で保存し、gears_init.jsと同じディレクトリに保存してほしい。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
<style type="text/css">
   tbody#employee-list td {
      cursor: pointer;
   }
   tbody#employee-list tr.selected {
      background-color: #CCCCFF;
   }
</style>

<!-- Gearsの初期化 -->
<script type="text/javascript" src="gears_init.js"></script>
<script type="text/javascript"><!--

// データベースオブジェクトの作成
var db = google.gears.factory.create('beta.database', '1.0');

// 現在選択されている従業員のID
var selectedEmployeeId;

/**
 * ドキュメントの読み込みが終わった際呼び出されます。
 */
function init() {
   // DBのオープン
   db.open("gears-crud");
   // 従業員テーブルの作成
   db.execute(
      "create table if not exists employee (" +
      " id integer primary key autoincrement," +
      " name text not null" +
      ")");
   // 検索
   searchEmployees();
}

/**
 * 従業員を検索して一覧表示します。
 */
function searchEmployees() {
   // selectクエリの発行
   var rs = db.execute("select * from employee order by id");
   var rows = "";

   // 一旦全ての行を削除
   var tbody = document.getElementById("employee-list");
   while (tbody.hasChildNodes()) {
      tbody.removeChild(tbody.lastChild);
   }
   try {
      // ResultSet#isValidRow()メソッドがtrueを返す間ループ
      while (rs.isValidRow()) {

         // 結果セットからIDを取得
         var id = rs.fieldByName("id");

         // DOMでテーブル行作成
         var row = document.createElement("tr");
         row.id = "row_" + id;

         // 行のonclickにイベントハンドラをセット
         // 以下のコードについては筆者のブログ記事を参照のこと
         // http://d.hatena.ne.jp/Syunpei/20070605/1181035316
         row.onclick = (function(id_) {
            return function() { employeeSelected(id_); }
         })(id);

         var idCell = document.createElement("td");
         idCell.appendChild(document.createTextNode(String(id)));

         var nameCell = document.createElement("td");
         nameCell.appendChild(document.createTextNode(rs.fieldByName("name")))

         row.appendChild(idCell);
         row.appendChild(nameCell);

         tbody.appendChild(row);

         // 結果セットのカーソルを先に進める
         rs.next();
      }
   } finally {
      if (rs) rs.close();
   }
}

/**
 * 従業員の新規登録を行います。
 */
function createEmployee() {
   var nameField = document.getElementById("name");
   var employeeName = nameField.value;
   if (employeeName.length > 0)
      // insert文の発行
      db.execute("insert into employee (name) values (?)", [employeeName]);
   searchEmployees();
   nameField.value = "";
}

/**
 * 従業員名の更新を行います。
 */
function updateEmployee() {
   if (!selectedEmployeeId) {
      return;
   }
   var nameField = document.getElementById("name");
   var employeeName = nameField.value;
   if (employeeName.length > 0)
      // update文の発行
      db.execute("update employee set name = ? where id = ?", [employeeName, selectedEmployeeId]);
   searchEmployees();
   nameField.value = "";
}

/**
 * 選択された従業員の削除を行います。
 */
function removeEmployee() {
   if (!selectedEmployeeId) {
      return;
   }
   // delete文の発行
   db.execute("delete from employee where id = ?", [selectedEmployeeId]);
   searchEmployees();
   selectedEmployeeId = null;
}

/**
 * 行が選択されたとき呼び出されます。
 */
function employeeSelected(id) {
   // 以前選択されていた行の選択解除
   var previousSelected = selectedEmployeeId;
   if (previousSelected) {
      var previousSelectedRow = document.getElementById("row_" + previousSelected);
      if (previousSelectedRow) previousSelectedRow.className = "";
   }
   // 新たに選択された行を記憶する
   var selectedRow = document.getElementById("row_" + id);
   if (selectedRow) {
      selectedRow.className = "selected";
      selectedEmployeeId = id;

      // 従業員名フィールドに名前を表示
      var nameField = document.getElementById("name");
      nameField.value = selectedRow.childNodes[1].innerHTML;
   }
}

--></script>
</head>

<body onload="init()">
<h2>従業員管理サンプル</h2>
<input type="textfield" size="20" id="name">

<input type="button" value="登録" onclick="createEmployee();">
<input type="button" value="更新" onclick="updateEmployee();">
<hr />
<input type="button" value="削除" onclick="removeEmployee();">
<table border="1">
   <thead>
      <tr>
         <th>従業員ID</th><th>名前</th>
      </tr>
   </thead>

   <tbody id="employee-list">
   </tbody>
</table>
</body>
</html>

そのディレクトリをApache HTTP ServerなどのHTTPサーバで公開し、GearsがインストールされたブラウザでWebページにアクセスすれば、実行できるはずだ。