本地数据库

本地数据库

本地数据库概念

HTML5 的一个重要特性是本地数据持久性,结合应用程序缓存能够实现离线状态下的正常工作。此外,本地数据持久性使移动应用程序更灵敏,使用的带宽更少,而且能够在低带宽场景中更高效地工作。HTML5 提供了一些本地数据持久性选项。第一个选项是 localstorage,它支持您使用一个简单的键值对来存储数据。IndexedDB支持您本地存储大量对象,并使用健壮的数据访问机制检索数据。我们这一节就讲解indexedDB

判断浏览器是否支持

indexedDB是window中的对象,所以使用下面的代码判断

//判断浏览器是否支持本地存储

if (window.indexedDB) {

alert("支持");

} else {

alert("不支持");

}

新建数据库

使用open方法新建数据库,代码如下

var request = window.indexedDB.open("数据库名称", 版本号);

open方法的作用

open方法的作用是新建或者打开数据库,如果指定的数据库不存在,则创建数据库;如果已经存在,则打开数据库

open方法参数

open方法接受两个参数

第一个参数是数据库名称。因为一个网站可以有多个本地数据库,所以要保证这个数据库名称是唯一的

第二个参数是数据库版本号。每一次改变数据库的结构,比如添加、修改、删除存储对象(表),都要变更版本号

这里我们着重说一下版本号的注意点。

版本号只能增,不能减。比如上次调用open方法,传入的版本号是2,再次调用的时候修改为1,则会报错

版本号可以为空。当版本号为空时,创建的数据库的版本号为1

实例

运行如下代码

if (window.indexedDB) {

//注意我们没有写版本号,则默认为1

var request= window.indexedDB.open("db1");

} else {

alert("不支持");

}

下面我们来看看数据库是否创建成功,以chrome为例,按下F12或者Fn+F12,打开开发者工具,选择“Resources”选项卡

我们看到左侧的indexedDB,展开来看看

这个db1就是我们刚刚创建的数据库,右边展示的是数据库的信息,分别说明了数据库所属的域,名称以及版本号

这是如果我们再次执行上面的代码,则不会再次创建db1数据库,而是打开,因为此数据库已经存在

修改上面的代码,将版本号改为2

if (window.indexedDB) {

//注意我们没有写版本号,则默认为1

var request= window.indexedDB.open("db1",2);

} else {

alert("不支持");

}

再次执行这段代码,看开发者工具中indexedDB变化(注意,要刷新之后才能看到变化。刷新方法:在indexedDB上右键-“Refresh indexedDB”)

但是如果现在想再次升级数据库版本,则应将数据库的版本号修改为>2的数字,如果改为<2的数字,比如1,则不会有任何作用

获取创建的数据库

数据库创建好之后,我们需要拿到创建的数据库的引用才能够操作数据库,如创建objectstore(表),操作数据等。

我们注意到open方法的返回值 request 了吗?但是它并是数据库的引用,open方法只是向浏览器发送了一个请求,请求新建或打开某个数据库,对象request有三个重要的事件,我们可以在这些事件中根据不同的情况编写不同的代码,首先我们熟悉一下这几个事件

onerror:当调用open方法发生错误时,会调用这个事件,如open方法中的版本号低于数据库的版本号

onsuccess:open方法成功执行时调用,如成功新建了数据库,或者成功打开了已有的数据库

onupgradeneeded:此事件只有在新建数据库和数据库版本号发生变化时才被调用。注意:此事件发生在onsuccess事件之前

总结:应该将对objectstroe的操作,如创建、修改、删除操作放在onupgradeneeded事件中,而不能放在onsuccess事件中,这些操作数据数据库结构的变更,属于升级操作,而onsuccess事件每次open方法都会执行,也会调用open方法的目的只是为了添加一条数据而已。

下面我们来编写完整的代码

window.onload = function() {

//声明变量用来存储数据库的引用

var mydb;

//判断浏览器是否支持本地存储

if (window.indexedDB) {

//注意我们没有写版本号,则默认为1

var request = window.indexedDB.open("db1", 2);

request.onerror = function(e) {

console.log("打开数据库时发生错误");

};

request.onsuccess = function(e) {

mydb = e.target.result;

console.log("打开数据库成功");

};

request.onupgradeneeded = function(e) {

mydb = e.target.result;

console.log("数据库版本变更成功");

};

} else {

alert("不支持");

}

}

console.log方法是为了在控制台中输出内容,用来调试

e.target.result获取的就是对数据库的引用,我们声明了一个全局变量mydb来存储这个引用。

这是使用indexedDB数据库一个比较完整的结构,接下来我们就创建objectStore

创建objectStore

objectStore概念

有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,我自己翻译成对象仓库,一个数据库中可以包含多个objectStore,objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。

那么这个键是什么呢?

键为何物

在objectStore中数据的存储方式与传统的关系型数据库不一样。比如要存储下面的信息

一个人的姓名是张三,年龄是20,性别是男,籍贯是保定

传统的关系型数据库的存储方式是这这样的:首先在表中创建字段,然后再每个字段下面添加值(鉴于每张表必须要有主键的原则,我们还必须为其添加一个业务无关列,比如 id),如下图

idnameagegenderaddress

1

张三

20

保定

好,这个id列就相当于objectstore中的键,目的是为了唯一标识每条数据。

但是在objectstore中数据的表示形式不是这样的,而是以键值对的形式存储数据

{name:"张三",age:20,gender:"男",address:"保定"}

我们会思考,如果还有另外一条一模一样的数据怎么办(同名同姓、想同年级、相同性别、相同籍贯的人太多了),如果某一天我们要找张三,到底找哪个呢?

所以在objectstore中也有键的概念,我们一起来看一下在indexedDB中,应该如何指定键

在indexedDB中,键有如下类型

键类型存储数据

不使用

任意值,但是没添加一条数据的时候需要指定键参数

keyPath

Javascript对象,对象必须有一属性作为键值

keyGenerator

任意值

都使用

Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性

大家不要晕,今天我们只介绍一种,keyPath,剩下的大家自己就能看懂了。keyPath的意思就是使用每条记录中的某个指定字段作为键值(keyPath),比如上面的数据

{name:"张三",age:20,gender:"男",address:"保定"}

我们修改一下,新增一个id

{id:"1001",name:"张三",age:20,gender:"男",address:"保定"}

我们将id的值作为唯一标识这条数据的键,就可以使用keyPath方式,具体使用方式在创建objectstore的使用会介绍

创建objectstore

修改onupgradeneeded事件中的代码

request.onupgradeneeded = function(e) {

mydb = e.target.result;

if (!mydb.objectStoreNames.contains("student")) {

mydb.createObjectStore("student", {

keyPath: "id"

});

};

};

mydb.objectStoreNames.contains方法用来判断数据库中是否存在名称为 student 的objectstore,如果没有则创建

createObjectStore方法用来创建objectstore,其接受两个参数,第一个参数是objectstore名称,第二个是为这个objectstore指定键的值,{keyPath: "id"}的意思是student采用keyPath类型的键,这个键的值就是数据库中id字段的值

当然,在执行这段代码之前,别忘了修改open方法中的版本号,否则这个事件是不会执行的(怎么样,被我说中了吧)

看下图(别忘了右键刷新)

也许现在你对这个“键”的概念还不是很清楚,没事,下面我们插入两条数据,一看数据你就明白了

向objectstore中插入数据

事务

在对数据进行操作之前(注意不是对数据库),需要开始一个事务。事务中需要指定该事务跨越哪些object store。也就是说,任何对objectstore中的数据的操作都要放在事务当中

事务具有三种模式

只读:read,不能修改数据库数据,可以并发执行

读写:readwrite,可以进行读写操作

版本变更:verionchange

下面我们看代码如何实现

在html中加入一个按钮,点击此按钮式向名为student的objectstore插入数据

为此按钮添加单击事件,代码如下

document.getElementById("btnAdd").onclick = function() {

//创建要添加的数据

var student = {

id:"1001",

name: "张三",

age: 20,

gender: "男",

address: "保定"

};

//创建针对student的事务

var transaction = mydb.transaction(["student"], "readwrite");

//从事务中获取要操作的objectstore

var obj = transaction.objectStore("student");

//添加数据

obj.add(student);

console.log("数据添加成功");

}

我们拼接了一个键值对的集合,其作为要插入到student中数据,因为objectstore只接受这种格式的数据,请先记住id的值

mydb.transaction方法用来开启事务,其接受两个参数,第一个是与这个事务相关联的objectstore的名称,注意使用了[],因为一个事务可以关联多个objectstore,第二个参数说明此事务是可读可写的,即可以在这个事务中读写数据

transaction.objectStore("student")方法在事务中获取要操作的objectstore

obj.add(student)方法用来向objectstore中插入数据

点击按钮后,刷新indexedDB,查看结果

我们看到,key的值就是键值对中id的值

添加多条数据

如果想添加多条数据,我们就需要修改一下代码

document.getElementById("btnAdd").onclick = function() {

//创建要添加的数据

var student = [{

id: "1002",

name: "张三",

age: 20,

gender: "男",

address: "保定"

}, {

id: "1003",

name: "李四",

age: 21,

gender: "男",

address: "国际庄"

}, {

id: "1004",

name: "李丹",

age: 22,

gender: "女",

address: "保定"

}];

//创建针对student的事务

var transaction = mydb.transaction(["student"], "readwrite");

//从事务中获取要操作的objectstore

var obj = transaction.objectStore("student");

//添加数据

for (var i = 0; i < student.length; i++) {

obj.add(student[i]);

};

console.log("数据添加成功");

}

效果如图

思考:为什么这次id的值从1002开始,而不是1001?自己试试

查询数据

这里的查询只能根据key的值查询,不能像传统的数据库那样,可以根据任意一个键值,如name、age等查询,如果要实现这种效果的话,需要配合indexedDB中的索引和游标使用

我们首先讲解根据key值查询

添加一个按钮,用于查询数据

document.getElementById("btnQuery").onclick = function() {

var transaction = mydb.transaction(["student"], "readwrite");

var obj = transaction.objectStore("student");

var request = obj.get("1002");

request.onsuccess = function() {

console.log("id为1002的人的姓名为" + request.result.name);

}

}

obj.get方法的作用是向数据库中的名称为student的objectstore请求键的值为1002对应的数据,请求的结果存储在request.result属性当中。

然后我们再onsuccess事件中获取name的值。

我们可以输出request.result的值看看

request.onsuccess = function() {

//console.log("id为1002的人的姓名为" + request.result.name);

console.log(request.result);

}

结果如下

更新数据

添加一个按钮,用于更新数据,代码非常简单,直接上代码

document.getElementById("btnUpdate").onclick = function() {

var transaction = mydb.transaction(["student"], "readwrite");

var obj = transaction.objectStore("student");

var request = obj.get("1002");

request.onsuccess = function() {

request.result.name="哈哈";

obj.put(request.result);

}

}

与查询方法很想,仍然需要在onsuccess事件中操作,首先更改request.result.name的值为新值,然后使用obj对象的put方法更新数据库

查看结果,发现值已经更改

删除数据

删除数据是最简单的

document.getElementById("btndel").onclick = function() {

var transaction = mydb.transaction(["student"], "readwrite");

var obj = transaction.objectStore("student");

obj.delete("1002");

}

结果如图

删除数据库

数据库也是可以删除的

document.getElementById("btndeldb").onclick = function() {

//关闭数据库连接

mydb.close();

indexedDB.deleteDatabase("db1");

}

删除之前应先调用close方法关闭当前的数据库连接,然后调用indexedDB.deleteDatabase方法根据数据库的名称删除即可

完整的案例

下面提供完整的案例,注意,第一次运行时应将数据库的版本号改为1

本地数据库

window.onload = function() {

//声明变量用来存储数据库的引用

var mydb;

//判断浏览器是否支持本地存储

if (window.indexedDB) {

//注意我们没有写版本号,则默认为1

var request = window.indexedDB.open("db1", 3);

request.onerror = function(e) {

console.log("打开数据库时发生错误");

};

request.onsuccess = function(e) {

mydb = e.target.result;

console.log("打开数据库成功");

};

request.onupgradeneeded = function(e) {

mydb = e.target.result;

if (!mydb.objectStoreNames.contains("student")) {

mydb.createObjectStore("student", {

keyPath: "id"

});

};

};

} else {

alert("不支持");

}

//添加数据

document.getElementById("btnAdd").onclick = function() {

//创建要添加的数据

var student = [{

id: "1002",

name: "张三",

age: 20,

gender: "男",

address: "保定"

}, {

id: "1003",

name: "李四",

age: 21,

gender: "男",

address: "国际庄"

}, {

id: "1004",

name: "李丹",

age: 22,

gender: "女",

address: "保定"

}];

//创建针对student的事务

var transaction = mydb.transaction(["student"], "readwrite");

//从事务中获取要操作的objectstore

var obj = transaction.objectStore("student");

//添加数据

for (var i = 0; i < student.length; i++) {

obj.add(student[i]);

};

console.log("数据添加成功");

}

//查询数据

document.getElementById("btnQuery").onclick = function() {

var transaction = mydb.transaction(["student"], "readwrite");

var obj = transaction.objectStore("student");

var request = obj.get("1002");

request.onsuccess = function() {

console.log("id为1002的人的姓名为" + request.result.name);

}

}

//更新数据

document.getElementById("btnUpdate").onclick = function() {

var transaction = mydb.transaction(["student"], "readwrite");

var obj = transaction.objectStore("student");

var request = obj.get("1002");

request.onsuccess = function() {

request.result.name="哈哈";

obj.put(request.result);

}

}

//删除数据

document.getElementById("btndel").onclick = function() {

var transaction = mydb.transaction(["student"], "readwrite");

var obj = transaction.objectStore("student");

obj.delete("1002");

}

document.getElementById("btndeldb").onclick = function() {

//关闭数据库连接

mydb.close();

indexedDB.deleteDatabase("db1");

}

}

参考资料

html5 本地mysql_html5本地数据库(一)相关推荐

  1. html5本地数据库 没有用,【HTML5初探之本地存储】如果没有数据库。。。

    导航 [初探HTML5之使用新标签布局]用html5布局我的博客页! [HTML5初探之form标签]解放表单验证.增加文件上传.集成拖放 [HTML5初探之绘制图像(上)]看我canvas元素引领下 ...

  2. webuploader结合php实现图片上传到本地和保存数据库

    webuploader结合php实现图片上传到本地和保存数据库,核心功能是以下三点: 一.上传前图片预览 二.上传图片到本地文件夹 三.上传图片路径和图片对应的设备编号到mysql数据库 Webupl ...

  3. 微信小程序 本地mysql_微信小程序系列之使用缓存在本地模拟服务器数据库

    微信小程序系列之使用缓存在本地模拟服务器数据库 现在将data.js这个文件视作是本地数据库的初始化数据,要做的第一件事就是讲这些初始化数据装进缓存中,以形成数据库的初始化数据 整个应用程序的生命周期 ...

  4. 将本地SQL Server数据库迁移到Azure SQL数据库

    In this article, we will discuss and understand a method to migrate an on-premises SQL Server databa ...

  5. 本地建mysql数据库_mysql 安装及新建本地数据库遇到的问题

    如果你只需要连接远程数据库,那么不需要安装mysql,直接安装mysql workbench,通过workbench就可以连接远程数据库.但是如果你需要自己在本地建立一个数据库,那么你肯定就需要安装m ...

  6. 搭建阿里云Linux版服务器+使用docker安装EMQ、Node-RED、MySQL+本地Navicat访问数据库(增删改查)——详细流程

    搭建阿里云Linux版服务器+使用docker安装EMQ.Node-RED.MySQL+本地Navicat访问数据库 云服务器基础搭建 注册云服务器 XShell简介 部署EMQ 部署docker 物 ...

  7. [HTML5]简单网页本地音乐播放器

    既然HTML5提出与本地交互方便,就想写个HTML5的本地音乐播放器.一开始问题主要集中在怎么读取本地文件路径,我想肯定可以用JS实现去操作本地文件(因为node.js很容易实现读取本地文件,但是原生 ...

  8. html开发android,使用HTML5开发Android本地应用(一)

    HTML5是现在最热门的技术之一,Android自带的WebKit浏览器对于HTML5有着不错的支持,而各种浏览器的最新版本都开始普遍的支持HTML5.使用HTML5开发手机应用的主要好处有两个:一个 ...

  9. plsql备份还原oracle数据库,(已实践)PLSQL本地还原Oracle数据库dmp文件

    这个方法很烂,导致重装Oracle时候处处出现问题,不建议使用这个方法,除非你以后不再用Oracle这个软件了,这个方法很烂,再评论一下. 第一,启动服务,(如果数据库处于启动状态,那么略过这一步) ...

  10. Java单元测试实践-25.在本地使用H2数据库进行单元测试

    Java单元测试实践-00.目录(9万多字文档+700多测试示例) https://blog.csdn.net/a82514921/article/details/107969340 1. 前言 使用 ...

最新文章

  1. 代码规范+设计模式落地之路
  2. idea 从svn导入多个项目_IDEA导入项目简单教程
  3. git创建、切换、合并、删除分支
  4. 构造函数的理解(构造函数与 init 方法)
  5. 小程序---模板的引用与使用
  6. 直播 | AAAI 2022论文解读:三⻆分解一致性约束的端到端语音翻译
  7. ajax 返回数据null,ajax post 返回的数据是null
  8. 数据结构——最小生成树之prime算法(与最短路径之迪杰斯特拉算法很像)
  9. mysql sphinx 中文搜索_sphinx+mysql+mmseg 实现中文全站搜索 安装配置文档
  10. 没有bug队——加贝——Python 练习实例 29,30
  11. appium屏蔽软键盘
  12. 【GIS导论】实验七 地图设计与输出
  13. android动态壁纸文件,DIY Android手机动态壁纸APK安装文件
  14. 力行《促进大数据发展行动纲要》 普元数据治理解决方案出炉
  15. 通过正则表达式提取泰坦尼克号字幕里的所有台词
  16. 计算机无法识别华为usb设备,华为路由A1插上USB储存设备无法识别怎么办
  17. 为什么快捷指令无法将媒体转换为文本_电脑端“快捷指令”——自动化神器Quicker了解一下...
  18. @Aspect注解使用场景
  19. CSS——移动端适配方案
  20. Xamainr 地图之webview初探

热门文章

  1. iOS开发网络篇—GET请求和POST请求(转)
  2. ie11只能用管理员身份打开解决办法
  3. Oracle RAC系列之:ASM基本操作维护
  4. 【本人秃顶程序员】SpringMVC工作原理详解
  5. 2.1.0 Python初识面向对象
  6. Debian9用户态下安装pipenv
  7. RESTful API 设计规范
  8. ThinkPHP的A方法,R方法,M方法,D方法区别
  9. mvc:annotation-driven/与mvc:default-servlet-handler/之间的一个问题
  10. maven gradle等三放jar包仓库