html5 数据存储之indexDB(一)
indexed Database API,或简称为indexDB,实在浏览器中保存结构化数据的一种数据库,indexDB是为了替代目前已被废弃的WBDSQL,indexDB的思想是创建一套API,方便保存和读取javascript对象,同事还支持查询及搜索。
1、数据库
indexDB 就是一个数据库,与Mysql或web sql 等这些你之前可能用过的数据库相似,indexDB最大的特点就是使用对象保存数据,而不是用表来保存数据,一个indexDB数据库,就是一组位于相同命名空间下的对象的集合。
使用indexDB的第一步就是打开它,即把要打开的数据库名传给index.open().如果传入的数据库已经存在,就会发送一个打开请求,如果传入数据库不存在,就会发送一个创建并打开它的请求,总之,调用index.open()会返回一个IDBRequest对象,在这个对象上可以添加onerror和onsuccess事件处理程序。先来看一个栗子:
var request,database;
request=indexedDB.open('admin');
request.οnerrοr=function(event){
alert("Something bad happend while trying to open:"+event.target.errorCode);
};
request.onsuccess=function(event){
database=event.target.result;
};
在这两个时间处理中,event.target都指向request对象,因此它们可以互换使用。如果响应的是onsuccess事件处理程序,那么event.target.result中将有一个数据库实例对象(IDBData-base),这个对象会保存在database变量中.如果发生错误,那event.target.errorCode中将保存一个错误码,表示问题的性质,以下就是可能出现的错误码(这个错误码适合所有操作)
IDBDatabaseException.UNKNOWN_ERR(1):意外错误,无法归类.
IDBDatabaseException.NON_TRANSIENT(2):操作不合法.
IDBDatabaseException.NOT_FOUND_ERR(3):未发现要操作的数据库。
IDBDatabaseException.CONSTRA_INT_ERR(4):违反了数据库约束。
IDBDatabaseException.DATA_ERR(5):提供给事物的数据不能满足要求.
IDBDatabaseException.NOT_ALLOWED(6):操作不合法
IDBDatabaseException.TRANSACTION_INACTIVE_ERR(7):试图重用已完成的事务。
IDBDatabaseException.ABORT_ERR(8):请求中断,未成功.
IDBDatabaseException.READ_ONLY_ERR(9):试图在只读模式下修改或写入数据。
IDBDatabaseException.TIMEOUT_ERR(10):在有效的时间内未完成操作
IDBDatabaseException.QUOTA_ERR(11):磁盘空间不足.
默认的情况下,indexDB数据库是没有版本号的,最好一开始就为数据库指定一个版本号,为此可以调用setVersion()方法,传入以字符串形式表示的版本号,同样调用这个方法也会返回一个请求对象,需要你指定事件处理程序。
if(database.version!='1.0'){
request=database.setVersion("1.0");
request.οnerrοr=function(event){
alert("Something bad happend while trying to open:"+event.target.errorCode);
}
request.onsuccess=function(event){
alert("database already initialized. Datebase name:"+database.name+",Version:"+database.varsion+");
}
}else{
alert("database already initialized. Datebase name:"+database.name+",Version:"+database.varsion+");
}
这个例子尝试把数据库的版本号设置为1.0,第一行先检测version属性,看是否已经为数据库设置相应的版本号。 如果没有,就调用setVersion()创建修改版本的请求。如果请求成功,显示一条消息,表示版本修改成功,在整个WEB应用中,随着对数据库结构的更新和修改,可能会产生很多歌不同版本的数据库。
2、对象存储空间
在建立了与数据库的链接之后,下一步就是使用对象存储空间(可以把对象存储空间想象成表),如果数据库的版本与你传入的版本不匹配,那么可能就需创建一个新的对象存储空间了,在创建对象存储空间之前,必须要想清楚你想要保存什么数据类型。
var user={
username:"008",
fristname:"James",
lastname:"Bond",
sex:"男"
}
有了这么一个对象,很容易想到username数据可以作为这个对象存储空间的键,这个username必须全局唯一,而且多数时候都要通过这个件访问数据,这一点,非常重要,因为创建对象存储空间时,必须制定这么一个键,以下就是为保存上述用户记录而创建对象存储空间的示例。
var store=db.createObjectStore("user",{keyPath:"username"})
其中第二个参数中的keyPath属性,就是空间中将要保存的对象的一个属性,而这个数据将作为存储空间的键来使用。
ok,现在有了一个存储空间的引用,接下来可以使用add()或者put()方法来向其添加数据,这两个方法都接受一个参数,即要保存的对象,然后这个对象就会被保存在存储空间中,这两个方法的区别在空间中已经包含键值相同的对象是就会体现出来,在这种情况下,add()会返回错误,而put()则会重写原有对象,简单滴说,可以把add()想象成插入新值,把put()想象成更新原有的值,再初始化对象空间时,可以使用类似下面这样的代码。
//user中保存着一批用户对象
var i=0,len=user.length
while(i<len){
store.add(user[i++])
}
每次调用add()或put()都会创建一个新的针对这个对象存储空间的跟新请求,如果想验证请求是否完成,可以把返回的请求对象保存在一个变量中,然后在指定onerror和onsuccess事件处理程序,创建了对象存储空间并向其添加数据后就该查询数据了。
3、事物
跨过创建对象存储空间这一步之后,接下来的所有操作都是通过事务来完成的,在数据库对象上调用transaction()方法可以创建事务,任何时候,只要想读取或修改数据,都要通过事务来组织所有操作,在最简单的情况下,你可以这样创建事务。
var transaction=db.transaction()
如果没有参数,就能通过事务来读取数据库中保存的对象,最常见的方式是传入要访问的亦或者多个对象存储空间。
var transaction=db.transaction("user")
这样就能保证只加载user存储空间的数据,以便通过事务进行访问,如果要访问多个对象存储空间,可以在第一个参数的位置上传入字符串数组
var transaction=db.transaction(["user","teacher"])
如前所述,这些事务都是以只读的方式访问数据,要修改访问方式,必须在创建事务时传入第二个参数,这个参数表示访问模式,用IDBTransaction接口定义如下常量表示read_only(0)表示只读,read_write(1)表示读写,read_change(2)表示改变。IE10+和FIREFOX4+实现的是IDBTransaction,chrome中则叫webkitIDBTransaction所以使用下面代码可以统一接口:
var transaction=window.IDBTransaction || window.webkitIDBTransaction;
有了这行代码就可以更方便的为transaction()指定第二个参数了
var transaction=db.transaction("user",IDBTransaction.READ_WRITE)
这个事务能够读写user存储空间。
取得了事务索引后,使用objectStore()方法并传入存储空间的名称,就可以访问特定的存储空间,然后,可以像以前一样使用add()和put()方法,使用get()方法可以取得值,使用delete()方法可以删除对象,而使用clear()则可以删除所有对象,get()和delete()方法都接受一个对象键作为参数,而所有这5个方法都会返回一个新的请求对象。
var request= db.transaction("user").objectStore("user").get("007");
request.οnerrοr=function(event){
alert("Did not get the object");
};
requrst.onsuccess=function(event){
var result=event.target.result;
alert(result.firstname);
};
因为一个事务可以完成任何多个请求,所以事务对象本身也有事件处理程序onerror和oncomplete这两个事件可以提供事务机的状态信息。
transaction.οnerrοr=function(event){
//整个事务被取消了
}
transactin.oncomplete=function(event){
//整个事务都成功完成了
}
注意,通过oncomplete时间对象(event)访问不到get()请求返回的任何数据,必须在相应请求的onsuccess事件处理程序中才能访问到数据。
游标,键范围,索引,并发问题会在之后介绍。