Nova PhoneGap框架 第四章 本地数据库
我一直想把EntityFramework(简称EF)的那一套搬过来,应用于HTML5 SQLite。 幸运的是,我几乎做到了,有些功能无法完成的那是因为SQLite本身不支持。至少从现在已经完成的功能来看,我们几乎可以像EF那样去操作数据库。
在我们这个框架中,所有对数据库的访问都封装在了命名空间"nova.data"下面。其下主要包括了以下类:
- nova.data.DbContext
 - nova.data.Entity
 - nova.data.Repository
 - nova.data.Queryable
 
下面我将逐一详细阐述。
4.1 nova.data.DbContext
这个类相当于是数据库的定义。我们定义的数据库的类都应该继承自这个类。下面让我们先来看个例子吧。

这段代码定义了一个数据库,但实际上里面只有一张表,关于表的定义我会在下一节中详述。这里唯一的一张表就是"this.targets", 类型是"nova.data.Repository",相当于EF中的DbSet,实现的都是仓储模式。
请注意上面的第6行代码,nova.data.DbContext构造函数的第2个参数是版本号(字符串)。这个版本号的神奇之处在于,当它改变的时候,那么在初始化数据库的时候(通常在index.html),整个数据库就会重新创建。如果你希望数据库在重新创建的时候能够带一些初始数据,那么你可以覆写initData方法。
让我们把目光再次投向第10行代码。上面我说了,这一行代码是在这个数据库中定义了一张表。如果还想添加更多的表怎么办呢?对于聪明的你来讲一定不成问题。只需要在这个at.domain.AtDbContext下增加一些属性,并且这些属性的类型都是nova.data.Repository。值得一提的是,repository的第一个参数是一个构造函数,并且类型必须继承自nova.data.Entity。具体的关于repository个entity的定义,我会在后面的内容中详细阐述。这里你只需知道如何定义一个数据库,如何往数据库中添加/删除/更新表。
4.2 nova.data.Repository
这个类相当于EF中的DbSet,跟nova.data.DbContext一起实现了仓储模式。所谓仓储模式,就是说任何对repository的增加/删除/更新操作都只有在调用了DbContext.saveChanges之后才会生效。我们这个框架中提供的数据访问也是这样一种模式,如此你便可以同时提交多条数据更改了,而不是每一次更改都要调用一次数据库。
这个类相当于EF中的DbSet,主要用于定义表。其第一个参数是实体类的构造函数,实体类需继承自nova.data.Entity, 第2个参数是字符串,及数据库中表的名字。
这个类下面有很多方法,我就不一一赘述了。发个截图吧,相信从方法的定义大概看得出是做什么的:

这个类实际我一直想着改造下的,那就是让它继承自nova.data.Queryable. 不过现在这样用着也满足需求,也挺方便。
这个类有个已知的BUG,会在本章末尾阐述。
4.3 nova.data.Entity
我在设计这个类的时候,我也试着模仿EF中的CodeFirst模式的代码。就是说每一个字段的数据类型在定义这个实体类的代码中体现,幸运的是我几乎实现了这样的功能。只要你在定义实体类的时候,给每一个属性指定一个初始值,那么在创建数据库的时候,就会根据这个初始值来指定数据类型。目前支持的数据类型有:integer, decimal,string, date,boolean。如下面的代码:

在我们的框架下开发应用程序,所有的本地数据库实体类都应该继承nova.data.Entity。
这个类只有一个属性integer id,这也是SQLite数据库每一张表默认都会带的字段。因此,在你的数据库实体类的定义中,不应该再定义id这个字段了。除了这个id属性,这个基类还定义了一些方法,主要是用于处理数据类型的。
这个类的另一个强大之处在于,以Target实体类为例,当你同时往数据库插入了多条target记录,并调用了dbContext.saveChanges方法时,每一个target的id会得到更新。这个特性也是模仿EF的,因为我们在使用EF的过程中发现这个特性实在太有用了。相信你在使用我们框架的过程中也会喜欢这个特性的。
4.4 nova.data.Queryable
这个类是模仿Linq中的IQueryable的,其工作原理也是和IQueryable类似。请看下面这行代码:
db.targets.where(“price >= 10”).where(“price < 20”).orderBy(“category”).thenBy(“name”).toArray(callback).
如果你熟悉Linq,那么这行代码你一定不会陌生。是的,我们的框架就实现了这样的功能。上面这行代码,在调用toArray之前,每一个查询/排序条件都没有提交到数据库,而是放在了内存当中,只有当调用了toArray时,才会执行数据库的查询。
请注意上面这行代码的第一个where,这个where方法实际上是repository中定义的,但返回的却是queryable,而后面的where和orderBy等都是queryable的实例方法。这正是模仿Linq设计的巧妙之处。
这个类的其他方法都比较一目了然了,就贴个截图吧:

4.5 常用例子
前面我把我们框架中对于本地数据库访问的每一个成员都做了详细的介绍,但如果你对JS面相对象或者EF不那么熟悉的话,可能还是看得有些云里雾里。好吧,下面我就贴一些常用的例子,相信这些例子一定能让你领略到这个框架的独特魅力。
4.5.1 定义数据库
先上代码:

这段代码只定义了一个targets表,你当然可以增加更多的表,只需要把第3行代码复制几份,然后改改名字就可以了。
4.5.2 定义实体类
先上代码:

这里定义了一个Target类,还有很多个实例方法,看上去跟普通的类没有什么区别,唯一的区别就是继承自nova.data.Entity.
4.5.3 查询

4.5.4 插入

4.5.5 更新

4.5.6 删除

4.6 已知问题
目前有1个问题无法解决。
当同时执行批量插入、批量更新、批量删除的时候会报错。因此,如果你想同时执行这些批量操作的话,那么应该让一种批量操作完成之后再执行另一个批量操作。
Nova PhoneGap框架 第四章 本地数据库的更多相关文章
- Nova PhoneGap框架 第五章 文件结构
		
一个好的项目架构必然有着合理的文件结构,如果一个项目的文件组织混乱,那么可以断言一定是项目架构有问题. 合理的文件结构能够帮你更清晰的管理你的文件,并且当需要添加新的文件的时候,你的程序员很清楚应该加 ...
 - Nova PhoneGap框架 第七章 设备事件处理
		
我们的框架包含了几种设备事件的处理,目的是为了让我们的程序员更容易的完成代码.这些事件包括:回退键(Android)和横竖屏切换事件. 7.1 Android回退键 首先来说说回退键的事件处理.当用户 ...
 - Nova PhoneGap框架 第三章 页面
		
页面在项目架构中是一个很重要的概念,它让我们能够将一个功能复杂的项目拆分成一个一个功能比较独立的小区域,这极大的提高了代码的可读性和可维护性. 在我们这个框架中,一个页面由JS和HTML两部分组成,首 ...
 - Nova PhoneGap框架 第六章 使用Mock
		
在我们的框架中引入了一个很重要的设计,那就是使用Mock. 这里的mock是指cordova.mock.js文件,它模拟了PhoneGap(Cordova)的API,从而可以在浏览器中运行测试我们的程 ...
 - Nova PhoneGap框架 第一章 前言
		
Nova PhoneGap Framework诞生于2012年11月,从第一个版本的发布到现在,这个框架经历了多个项目的考验.一直以来我们也持续更新这个框架,使其不断完善.到现在,这个框架已比较稳定了 ...
 - Nova PhoneGap框架 第二章 理解index.html
		
跟绝大多数PhoneGap程序一样,Index.html是程序的入口.这个页面应该完成应用程序的初始化工作. 首先,让我们来看看这个页面通常都长什么样子: 下面我将一一解释这个页面都做了哪些初始化工作 ...
 - Nova PhoneGap框架 总结
		
Nova PhoneGap Framework 是完全针对PhoneGap应用程序量身定做的,在这个框架下开发的应用程序很容易实现高质量的代码,很容易让程序拥有很好的性能和用户体验. 在经历了多个项目 ...
 - Nova PhoneGap框架 第八章 滚动条
		
你可能会疑惑为什么滚动条这么常见的功能会在这里单独列出,但如果你有过PhoneGap开发经验的话,你就会发现要在Android 2.3 里面实现滚动条那真不是一件容易的事. 8.1 概述 目前主流的P ...
 - Nova PhoneGap框架 第九章 控件
		
我们的框架中也提供了一些常用的控件,这些控件大多都依赖于我们的框架,也正是在我们的框架下才使得实现这些控件的变得更简单.但是我们的框架是不依赖与这些控件的,如果你用不上这些控件,你完全可以把相关的代码 ...
 
随机推荐
- 浅析/dev/shm
			
一,/dev/shm 概念 /dev/shm 是一个tmpfs文件系统,临时文件系统,是基于内存的文件系统,也就是说/dev/shm中的文件是直接写入内存的,而不占用硬盘空间. 在Centos和Red ...
 - DDD建模案例----“视频课程”场景
			
接触领域驱动设计DDD有一年多的时间了,中间看过不少书,参与过一些讨论(ENode QQ群).目前对DDD的认知还停留在理论阶段,所以对领域建模非常感兴趣,这里说的建模是指以DDD的思想为指导再加上D ...
 - 【iOS】Jenkins Gitlab持续集成打包平台搭建
			
Jenkins Gitlab持续集成打包平台搭建 SkySeraph July. 18th 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点: ...
 - 配置mongoDB服务
			
上一节说到mongoDB的环境搭建,但是那种方法启动mongoDB太繁琐了. 今天先说说简化mongoDB启动的配置. 首先在命令行中运行的”C:\Program Files\MongoDB 2.6 ...
 - XOR Swap
			
swap(a, b): a ^= b b ^= a a ^= b 先明确一下,a ^ a = 0,同时对于一切数x ^ 0 = x 可以这样理解,第三行: b ^= a b ^= a ^ b b = ...
 - 毕业论文中使用的技术—FileReader接口
			
用来把文件读入内存,并且读取文件中的数据. FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据 FileReader接口的方法 方法名 参 ...
 - UGUI全面实践教程
			
UGUI全面实践教程 试读文档下载地址:http://pan.baidu.com/s/1hq3UYGk 介绍:UGUI是Unity官方推出的最新UI系统.本教程为国内唯一的UGUI专向资料.本教程 ...
 - 转:看看 Delphi XE2 为 VCL 提供的 14 种样式
			
http://www.linuxso.com/linuxbiancheng/8889.html 其实只提供了 个 vsf 样式文件, 还有默认的 Windows 样式, 共 种. 在空白窗体上添加 L ...
 - 【转】使用Spring MVC统一异常处理实战
			
方法一:使用SimpleMappingExceptionResolver实现异常处理 //在Spring的配置文件applicationContext.xml中增加以下内容: <bean cla ...
 - 使用Jmeter录制web脚本
			
1:启动Jmeter: 2:选择测试计划,右键->添加->Threads(users)>线程组 3:选择这个线程组,右键->添加->配置元件->HTTP请求默认值, ...