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框架 第九章 控件
我们的框架中也提供了一些常用的控件,这些控件大多都依赖于我们的框架,也正是在我们的框架下才使得实现这些控件的变得更简单.但是我们的框架是不依赖与这些控件的,如果你用不上这些控件,你完全可以把相关的代码 ...
随机推荐
- 不注册COM在Richedit中使OLE支持复制粘贴
正常情况下在Richedit中使用OLE,如果需要OLE支持复制粘贴,那么这个OLE对象必须是已经注册的COM对象. 注册COM很简单,关键问题在于注册时需要管理员权限,这样一来,如果希望APP做成绿 ...
- select2 清空数据
最近用select2插件,发现用jquery重置不好使,最后搜罗了一把发现下面这个方法可以间接的实现,有空还得看看插件的API $('#integratorId').select2('data', n ...
- 国外程序员整理的Java资源大全分享
Java 几乎是许多程序员们的入门语言,并且也是世界上非常流行的编程语言.国外程序员 Andreas Kull 在其 Github 上整理了非常优秀的 Java 开发资源,推荐给大家. 译文由 Imp ...
- 将Unreal4打包后的工程嵌入到Qt或者桌面中
#include "widget.h" #include "ui_widget.h" #include "windows.h" #inclu ...
- java function retry wrapper
import java.util.concurrent.Callable; /** * Created by huahui.yang on 1/29/16. */ public class Retry ...
- unity3D项目中如何避免硬代码(C#)
平时做项目,代码中是不允许出现硬代码的,一般我们是怎么处理的呢? 那么硬代码又是什么呢? 我们俗称的硬代码:eg: label.text = "欢迎来到梦幻岛"; 这样我们俗 ...
- Codeforces Round #377 (Div. 2)
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; in ...
- 简述HTML DOM及其节点分类
在JavaScript中,document这个对象大家一定很熟悉,哪怕是刚刚开始学习的新人,也会很快接触到这个对象.而document对象不仅仅是一个普通的JavaScript内置对象,它还是一个巨大 ...
- IDEA+Tomcat+JRebel热部署1
所需资源下载: jrebel_6.4.2a 概述 JRebel是一个J2EE热部署的工具.使用它可以减少浪费8-18%的开发时间在项目的构建和部署上.之前只是听说过,一直没有实践,今天实际使用了一把 ...
- 关于textarea中换行、回车、空格的识别与处理
需求:在textarea中输入文字,提交给后台后,后台输出在另一个页面,文字按原格式显示. 问题:如何还原输入框中的换行和空格? 兼容性:IE9以上.FF.chrome在换行处匹配/\n/ ...