Edited at

ブラウザのDBにアクセスする

More than 1 year has passed since last update.

ブラウザに情報を保存する仕組みはいくつかありますが、その中の一つであるWeb SQL DatabaseというAPIを紹介します。


目的


  • Web SQL Databaseを知る

  • TODOアプリを作る


Web SQL Databaseとは

冒頭でも言いましたが、ブラウザにデータを保存する仕組みの一つです。CookieやWeb StrageのKVS形式とは違い、SQLでデータの保存、呼び出しをすることができるSQLiteベースのブラウザDBとなります。残念ながらHTML5の標準仕様に入ることはなかったものの、多くの主要ブラウザ(Google Chrome、Safari、Firefox、Androidブラウザなど)でサポートされている機能です。

webdb.JPG

DBはサーバサイドで管理することが多いと思いますが、クライアントにそれなりの情報を持たせるとなると用途が難しそうだし、サーバサイドとの同期をとったり管理が大変そう。けど、上手く使えばサーバアクセスの回数を減らしてサーバ負荷を軽減することができそうですね。クライアントにDBがあるので、通信速度にストレスを感じることもなさそうです。


基本操作

基本となる操作を紹介します。実装はJavaScriptで行います。


DBを開く

var name = 'localdb'

var version = '1.0'
var description = 'Web SQL Database'
var size = 2 * 1024 * 1024
var db = openDatabase(name, version, description, size)

openDatabaseメソッドに引数を渡して実行し、データベースオブジェクトを作成します。指定したDBが存在するならばそのDBを、存在しないならば作成して開きます。


クエリの実行

var db = openDatabase(name, version, description, size)

db.transaction(function (tx) {
tx.executeSql(SQL, [パラメータ], 成功コールバック, 失敗コールバック)
})

こんな感じでクエリを実行します。引数はSQLだけでも実行できます。


検索

db.transaction(function (tx) {

tx.executeSql('select id, name from user', [],
function (tx, results) {
// SUCCESS
for (i = 0; i < results.rows.length; i++){
console.log(results.rows.item(i).id)
console.log(results.rows.item(i).name)
}
},
function(err){
// ERROR
})
})

こんな感じで検索結果を取得します。


追加 更新 削除

db.transaction(function (tx) {

tx.executeSql('insert into user (id, name) values (?, ?)', [1, '金田'])
tx.executeSql('update user set name = ? where id = ?', ['', 1])
tx.executeSql('delete from user where id = ?', [1])
})

更新系はこんな感じになります。


TODOアプリ

ここまでの基本操作を使って今回はTODOアプリを作りました。ソースはGitHubにあります。

ディレクトリ構成はこんな感じ。

WebSqlDatabase

├── bundle.js <- src下をbrowserifyしたやつ
├── index.html
└── src
├── Index.js
├── TodoDao.js
└── jquery-3.2.1.min.js <- ダウンロードしとく

画面にはTODOを入力するテキストボックスと登録するボタン、それと登録済みのTODOを表示するテーブルを用意します。


index.html

<!DOCTYPE html>

<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Web SQL Database</title>
</head>
<body>
<input type="text" name="todo" />
<button type="button" name="register">登録</button>
<table id="table">
<thead>
<tr>
<th>No</th>
<th>Todo</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<!-- TODOを追加していく -->
</tbody>
</table>

<script src="bundle.js"></script>
</body>
</html>


ボタンを押下するとTODOを登録し、テーブルに表示します。登録されたTODOと同じ並びに更新と削除ボタンを用意します。更新はテキストボックスに入力されたTODOで更新します。


Index.js

var TodoDao = require('./TodoDao')

var $ = require('./jquery-3.2.1.min')

// DAOインスタンス
var tododao = new TodoDao()

$(document).ready(function(){
// イベントハンドラ登録
$('input[name=todo]').keyup(function(v){
$('button[name=register], button[name=edit]')
.prop('disabled', $(this).val() == 0)
})
$('button[name=register]').on('click', register)
$('#table tbody').on('click', 'tr td button[name=edit]', edit)
$('#table tbody').on('click', 'tr td button[name=remove]', remove)

init()
})

// 初期化(全件表示)
var init = function(){
// TODO表の削除
$('#table tbody').empty()
// TODO表の表示
tododao.findAll(function(list){
$.each(list, function(i, e){
$('#table tbody').append(`
<tr>
<td>
${i+1}</td>
<td>
${e.todo}</td>
<td><button type="button" name="edit" value="
${e.id}">更新</button></td>
<td><button type="button" name="remove" value="
${e.id}">削除</button></td>
</tr>
`
)
})

// TODOテキストボックス、ボタンの初期化
$('input[name=todo]').val('').focus().keyup()
})
}

// 登録
var register = function(){
var todo = $('input[name=todo]').val()
tododao.insert(todo, init)
}

// 更新
var edit = function(){
var id = $(this).val()
var todo = $('input[name=todo]').val()
tododao.update(id, todo, init)
}

// 削除
var remove = function(){
var id = $(this).val()
tododao.remove(id, init)
}


DAOは別ファイルにしています。


TodoDao.js

var TodoDao = function(){

var name = 'localdb'
var version = '1.0'
var description = 'Web SQL Database'
var size = 2 * 1024 * 1024
var db = openDatabase(name, version, description, size)

// テーブル作成
db.transaction(function(tx){
tx.executeSql(`
create table if not exists todo (
id integer primary key autoincrement,
todo varchar
)
`
)
})

// 全件検索
this.findAll = function(callback){
db.transaction(function (tx){
tx.executeSql('select * from todo', [],
function (tx, results){
var list = []
for (i = 0; i < results.rows.length; i++){
list.push({
id: results.rows.item(i).id,
todo: results.rows.item(i).todo
})
}
callback(list)
})
})
}

// 登録
this.insert = function(todo, callback){
db.transaction(function (tx){
tx.executeSql('insert into todo (todo) values (?)', [todo], callback)
})
}

// 更新
this.update = function(id, todo, callback){
db.transaction(function (tx){
tx.executeSql('update todo set todo = ? where id = ?', [todo, id], callback)
})
}

// 削除
this.remove = function(id, callback){
db.transaction(function (tx){
tx.executeSql('delete from todo where id = ?', [id], callback)
})
}

}

module.exports = TodoDao


ではindex.htmlにアクセスしてブラウザで動作確認してみます。

wsd-min.gif

DBなので、ブラウザの別オブジェクトからも同じデータが参照できているのがわかりますね。当然ブラウザを閉じてもデータが保持されます。


最後に

Web SQL Databaseは簡単に扱えるのですが、実はブラウザDBとしてはIndexedDBというAPIの方が推奨されています。しかし、こちらもサポートしているブラウザは多いので、使用を検討しても良いんじゃないかと思いました。