構造化データ非同期ストレージ(Indexed Database API)

レコードの操作

レコードの追加や削除は、IDBDatabaseオブジェクト(変数db)のtransaction()メソッドを通して非同期に実行する。オブジェクトストアの生成は、IDBOpenDBRequestオブジェクト(変数openreq)のonupgradeneededプロパティにセットしたコールバック関数で処理してきたが、レコードの操作はonsuccessプロパティにセットしたコールバック関数で処理する。
次のサンプルは、データベースとオブジェクトストアを生成し、その後レコードを1つ追加する。

<script type="text/javascript">
$(function(){
  var result = $('#result');
  // IDBFactoryオブジェクトを取得
  var idb = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
  if( !idb ) { 
     $('<p>indexedDBをサポートしていない</p>').appendTo(result);
     return;
  }
  $('#exec').click(function(){
    // データベース名を得る
    var input_el = document.querySelector("#name");
    var valid = input_el.checkValidity();
    if(valid === false){
      alert(input_el.validationMessage);
      return;
    }

    var dbname = input_el.value;
    var deletereq = idb.deleteDatabase(dbname);
    // DB接続
    var openreq = idb.open(dbname,1);
    // DB接続に失敗したときの処理
    openreq.onerror = function(event){
      var error = event.taget.error;
      $('<p>DB接続に失敗しました ' + error.name + ' ' + error.message + '</p>').appendTo(result);
    }

    // DB生成に成功したときの処理
    openreq.onupgradeneeded = function(event){
      // IDBDatabaseオブジェクトを取得
      var db = event.target.result;
      // オブジェクトストア生成(IDBObjectStoreオブジェクト)
      var params = { keyPath: "id",autoIncrement:true };
      var store = db.createObjectStore("mystore",params);
      // インデックス生成
      var index_params = { unique:false };
      store.createIndex("name_index","name",index_params);
    }

    // DB接続に成功したときの処理
    openreq.onsuccess = function(event){
      // IDBDatabaseオブジェクトを取得
      var db = event.target.result;
      // IDBTransactionオブジェクトを取得
      var tansaction = db.transaction(["mystore"],"readwrite");
      // IDBObjectStoreオブジェクトを取得
      var store = tansaction.objectStore("mystore");
      // レコード追加開始(IDBRequestオブジェクト)
      var putreq = store.put({name:"商品1",price:500});
      // レコード追加が成功したときの処理
      putreq.onsuccess = function(){
        $('<p>レコードの追加に成功しました。</p>').appendTo(result);
        db.close();
      }
    }
  });
});
</script>
</HEAD>
<BODY>
<p>レコードの操作</p>
<form action="#" method="post" id="register">
 <label for="name">データベース名:</label>
 <input type="text" name="name" id="name" required>
 <input id="exec" type="button" value="実行">
</form>
<div id="result"></div>
</BODY>

IDBOpenDBRequestオブジェクト(変数openreq)のonsuccessプロパティにセットしたコールバック関数で、レコードの操作を行う。
①まず、IDBDatabaseオブジェクト(変数db)のtransaction()メソッドを使って、IDBTransactionオブジェクト(変数transaction)を取得する。
このメソッドの第一引数には、レコードを操作するオブジェクトストア名の配列を指定する。第二引数にはレコードのアクセスモードを文字列で指定する。読み取るだけならば”readonly”を、書き込みも必要ならば”readwrite”を指定する。
②次に、IDBTransactionオブジェクト(変数transaction)のobjectStore()メソッドから、オブジェクトストアを表すIDBObjectStoreオブジェクト(変数store)を取得する。このオブジェクトが操作するオブジェクトストアを表す。
③最後に、IDBObjectStore(変数store)のput()メソッドを使って、レコードを追加する。このメソッドはIDBRequestオブジェクト(変数putreq)を返す。put()メソッド処理は非同期のため、レコード追加の成功判定をする場合には、onsuccessプロパティにコールバック関数を指定する。
④このサンプルでは、オブジェクトストアを作る際に、パラメータkeyPathに”id”を、さらに、autoIncrementにtrueを指定しているため、レコードを追加する際にidに相当する値は自動採番されるため、主キーとなるidの値は必要としない。もしautoIncrementをfalseにセットしたのであれば、その値はレコード登録の都度、指定しなければならない。
⑤IDBObjectStoreオブジェクトには、put()メソッドの他にさまざまなメソッドが用意されている。

IDBObjectStoreオブジェクトのレコード操作メソッド
メソッド 説明
put(value) 引数valueに指定したオブジェクトデータを追加する。ただし、重複が許されないカラムが存在し、既存のデータにそのカラムが重複した場合は、そのデータを上書きする。
add(value) 引数valueに指定したオブジェクトデータを追加する。
delete(key) 引数valueに指定した値に一致する主キーを持つレコードを削除する。
get(key) 引数keyに指定した値に一致する主キーを持つレコードを検索する。
clear() オブジェクトストアの全レコードを削除する。

これらのメソッドの処理はすべて非同期である。これらのメソッドを実行するとIDBRequestオブジェクトを返す。このオブジェクトのonsuccessプロパティに、処理が成功したときのコールバック関数をセットして後続の処理を行う。
次のサンプルは、オブジェクトストアに100個のレコードを追加する。

<script type="text/javascript">
$(function(){
  var result = $('#result');
  // IDBFactoryオブジェクトを取得
  var idb = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB;
  if( !idb ) { 
     $('<p>indexedDBをサポートしていない</p>').appendTo(result);
     return;
  }
  $('#exec').click(function(){
    // データベース名を得る
    var input_el = document.querySelector("#name");
    var valid = input_el.checkValidity();
    if(valid === false){
      alert(input_el.validationMessage);
      return;
    }

    var dbname = input_el.value;
    var deletereq = idb.deleteDatabase(dbname);
    // DB接続
    var openreq = idb.open(dbname,1);
    // DB接続に失敗したときの処理
    openreq.onerror = function(event){
      var error = event.taget.error;
      $('<p>DB接続に失敗しました ' + error.name + ' ' + error.message + '</p>').appendTo(result);
    }

    // DB生成に成功したときの処理
    openreq.onupgradeneeded = function(event){
      // IDBDatabaseオブジェクトを取得
      var db = event.target.result;
      // オブジェクトストア生成(IDBObjectStoreオブジェクト)
      var params = { keyPath: "id",autoIncrement:true };
      var store = db.createObjectStore("mystore",params);
      // インデックス生成
      var index_params = { unique:false };
      store.createIndex("name_index","name",index_params);
    }

    // DB接続に成功したときの処理
    openreq.onsuccess = function(event){
      // IDBDatabaseオブジェクトを取得
      var db = event.target.result;
      // IDBTransactionオブジェクトを取得
      var tansaction = db.transaction(["mystore"],"readwrite");
      // IDBObjectStoreオブジェクトを取得
      var store = tansaction.objectStore("mystore");
      // 100レコード追加
      var num = 0;
      function putRecords(){
        num++;
        if(num <= 100){
          var putreq = store.put({name:"商品" + num,price:num * 100});
          putreq.onsuccess = function(){
            putRecords();
          }
        }else{
          $('<p>レコードの追加に成功しました。</p>').appendTo(result);
          db.close();
        }
      }
      putRecords();
    }
  });
});

</script>
</HEAD>
<BODY>
<p>レコードの操作</p>
<form action="#" method="post" id="register">
 <label for="name">データベース名:</label>
 <input type="text" name="name" id="name" required>
 <input id="exec" type="button" value="実行">
</form>
<div id="result"></div>
</BODY>