代码地址如下:
http://www.demodashi.com/demo/12422.html

前言

移动端的数据库选型一直是一个难题,直到前段时间看到了WeMobileDev(微信前端团队)放出了第三个开源组件-WCDB

WCDB(WeChat DataBase)是微信官方的移动端数据库组件,致力于提供一个高效、易用、完整的移动端存储方案

项目目录

微信团队怎么说

  • 基于SQLCipher

  • WCDB-iOS/Mac

  • WCDB-Android

  • 数据库损坏修复工具WDBRepair

背景

WCDB的出现可以说解决了目前移动端数据库的几个难点

  • 首先在选型上,FMDB的SQL拼接、难以防止的SQL注入;CoreData虽然可以方便ORM,但学习成本高,稳定性堪忧,而且多线程鸡肋;另外基于C语言的sqlite我想用的人也应该不多;除了上述关系型数据库之外然后还有一些其他的Key-Value型数据库,如我用过的Realm,对于ObjC开发者来说,上手倒是没什么难度,但缺点显而易见,需要继承,入侵性强,对于单继承的OC来说这并不理想,而且对于集合类型不完全支持,复杂查询也比较无力。
  • 高效
    • 多线程高并发:WCDB支持多线程读与读、读与写并发执行,写与写串行执行。

    • 批量写操作性能测试:

      ops/sec
      458000
      161000
  • 易用 WCDB支持一句代码即可将数据取出并组合为object
    • WINQ(WCDB语言集成查询):通过WINQ,开发者无须为了拼接SQL的字符串而写一大坨胶水代码。

    • ORM(Object Relational Mapping):WCDB支持灵活、易用的ORM。开发者可以很便捷地定义表、索引、约束,并进行增删改查操作。

    • 像这样

      [database getObjectsOfClass:WCTSampleConvenient.class
      
      		fromTable:tableName 
      
      		where:WCTSampleConvenient.intValue>=10 
      
      		limit:20];
  • 完整
    • 加密:WCDB提供基于SQLCipher的数据库加密。
    • 损坏修复:WCDB内建了Repair Kit用于修复损坏的数据库。
    • WCDB提供接口直接获取SQL的执行耗时,可用于监控性能。
    • 反注入:WCDB内建了对SQL注入的保护

ORM

在WCDB内,ORM(Object Relational Mapping)是指

  • 将一个ObjC的类,映射到数据库的表和索引;

  • 将类的property,映射到数据库表的字段;

这一过程。通过ORM,可以达到直接通过Object进行数据库操作,省去拼装过程的目的。

WCDB通过内建的宏实现ORM的功能。如下

PS:但我不建议这么做,首先要避免在.h文件中引用<WCDB/WCDB.h>,因为你一旦引用,就需要改变.m文件为.mm文件,因为WCDB是基于objectiveC++;你可以使用Category特性将其隔离,在category中引用<WCDB/WCDB.h>,并遵守WCTTableCoding协议,使用WCDB_PROPERTY将声明绑定到数据库表的字段。然后在模型类中引用category。达到不印象Controller和View的目的。这点官方wiki中也有提到,使用文件模板来创建。具体请见Demo

对于一个已有的ObjC类,

  • 引用WCDB框架头文件#import <WCDB/WCDB.h>,并定义类遵循WCTTableCoding协议

  • WCDB_PROPERTY用于在头文件中声明绑定到数据库表的字段。

  • WCDB_IMPLEMENTATION,用于在类文件中定义绑定到数据库表的类。同时,该宏内实现了WCTTableCoding。因此,开发者无须添加更多的代码来完成WCTTableCoding的接口

  • WCDB_SYNTHESIZE,用于在类文件中定义绑定到数据库表的字段。

  • WCDB_PRIMARY用于定义主键

  • WCDB_PRIMARY_AUTO_INCREMENT 用于定义自增主键

  • WCDB_INDEX用于定义索引

  • WCDB_UNIQUE用于定义唯一约束

  • WCDB_NOT_NULL用于定义非空约束

CRUD

得益于ORM的定义,WCDB可以直接进行通过object进行增删改查(CRUD)操作。

  • //插入
    Person *man = [[Person alloc] init];
    man.isAutoIncrement = YES;
    man.name = @"Hello, WCDB!";
    man.age = 12;
    return [database insertObject:man into:TABLE_WCDB_NAME];
  • return [database deleteObjectsFromTable:TABLE_WCDB_NAME where:Person.studentId == studentId];
  • Person *person = [[Person alloc] init];
    person.name = content;
    return [database updateRowsInTable:TABLE_WCDB_NAME onProperties:Person.name withObject:person where:Person.studentId == studentId];
  • NSArray<Person *> * person = [database getObjectsOfClass:Person.class fromTable:TABLE_WCDB_NAME orderBy:Person.localID.order()];

Transaction

WCDB内可通过两种方式执行Transaction(事务),一是runTransaction:接口

这种方式要求数据库操作在一个BLOCK内完成,简单易用。

另一种方式则是获取WCTTransaction对象

WCTTransaction对象可以在类或函数间传递,因此这种方式也更具灵活性。

WINQ

WINQ(WCDB Integrated Query,音'wink'),即WCDB集成查询,是将自然查询的SQL集成到WCDB框架中的技术,基于C++实现。

  • 免去拼接SQL字符串、防注入
  • 借助IDE代码提示和编译器语法检查
  • 对于一个已绑定ORM的类,可以通过className.propertyName的方式,获得数据库内字段的映射
  • WINQ的接口包括但不限于:
    • 一元操作符:+、-、!等
    • 二元操作符:||、&&、+、-、*、/、|、&、<<、>>、<、<=、==、!=、>、>=等
    • 范围比较:IN、BETWEEN等
    • 字符串匹配:LIKE、GLOB、MATCH、REGEXP等
    • 聚合函数:AVG、COUNT、MAX、MIN、SUM等
    • ...

原理

  • 初衷,适应WCDB+ORM解决SQL字符串的代码冗余和难以被编译器进行语法检查而造成的错误和时间浪费。SQL字符串太容易被注入
  • SQL抽象
  • 封装常用操作,覆盖80%的使用场景
  • 暴露底层接口,适配剩余20%的特殊情况
  • 定义常用操作
  • 特殊场景所暴露的底层接口,应该以什么形式存在?
  • SELECT、DISTINCT、ALL等等大写字母是keyword,属于SQL的保留字。
  • result-column、``table-or-subquery、expr等等小写字母是token。token可以再进一步地展开其构成的语法规则。
  • 将固定的keyword,封装为函数名,作为连接。
  • 将可以展开的token,封装为类,并在类内实现其不同的组合。
  • 在语法规则中,WHERE、LIMIT等都接受expr作为参数。因此,不管SQL多么复杂,StatementSelect也只接受Expr的参数。而其组合的能力,则在Expr类内实现。

数据库修复

  • 官方的Dump恢复方案

    • 遍历sqlite_master表,将未损坏的表和已损坏的前半部分读取出来将dump 出来的SQL语句逐行执行,最终可以得到一个等效的新DB

      功率约为30%。
    • 第一页就损坏后续无法读取
  • 备份恢复方案
    • COPY
    • 在DB完好的时候执行.dump
    • Backup API: SQLite自身提供的一套备份机制,按 Page 为单位复制到新 DB, 支持热备份。
    • 最终选择Dump + 压缩,恢复成功率达到72%
  • 解析B-tree恢复方案(RepairKit)
    • 成功率约为78%
  • 不同方案的组合
    • RepairKit 尝试恢复最新数据
    • 备份恢复 遇到错误填补漏缺
    • Dump 最后的尝试

For Android

  • 基本功能

    • 基于SQLCipher的数据库加密
    • 使用连接池实现并发读写
    • 内建 Repair Kit 可用于修复损坏数据
    • 针对占用空间大小优化的数据库备份/恢复功能
    • 日志输出重定向以及性能跟踪接口
    • 内建用于全文搜索的 mmicu FTS3/4 分词器
  • 接入与迁移

    • WCDB for Android 可通过 Maven 或 AAR 包引用,API 接口与 Android SDK 非常相近, 所以将已有的 App 迁移到 WCDB 是相当容易的。
    • Android 接入与迁移
  • 数据库修复

  • 从源码编译

    • 你可以使用预编译的依赖库(OpenSSL crypto 和 SQLCipher)来编译 WCDB for Android, 使用 Gradle 或 Android Studio 皆可。Android Studio 请导入 android 目录作为 Root Project。
    • 编译 WCDB 需要安装 Android NDK r11c 或以上,并在 android/local.properties 上配置好 SDK 与 NDK 路径。Android Studio 一般会帮你配置好。
    • 如果你需要自己编译 OpenSSL 等依赖项,你需要一个 Bash 环境(Windows 可以安装 Cygwin 或 MSys)、target 为本机的 C 编译器(如 GCC)、Perl 5 以及 Tcl。之后执行下面命令即可编译依赖项。

参考资料

微信移动端数据库组件WCDB系列(一)-iOS基础篇

微信移动端数据库组件WCDB系列(二) — 数据库修复三板斧

微信移动端数据库组件WCDB系列(三) — WINQ原理篇

微信移动数据库组件WCDB(四) — Android 特性篇微信开源组件WCDB漫谈及Demo

代码地址如下:
http://www.demodashi.com/demo/12422.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

微信开源组件WCDB漫谈及Demo的更多相关文章

  1. .net 开源组件

    文章转自:http://www.cnblogs.com/asxinyu/p/dotnet_opensource_project_3.html   在前2篇文章这些.NET开源项目你知道吗?让.NET开 ...

  2. 【2015上半年总结】js开源组件开发系列索引

    js开源组件开发系列一索引 2015.8 by 田想兵 个人网站 从3月份进入新公司以来,时经五个月,我以平均每周1个小组件的速度,已经完成的js组件有22个之余了,已基本上全部用到实际项目中,这些小 ...

  3. [js开源组件开发]network异步请求ajax的扩展

    network异步请求ajax的扩展 在日常的应用中,你可能直接调用$.ajax是会有些问题的,比如说用户的重复点击,比如说我只希望它成功提交一次后就不能再提交,比如说我希望有个正在提交的loadin ...

  4. [js开源组件开发]数字或金额千分位格式化组件

    数字或金额千分位格式化组件 这次距离上一个组件<[js开源组件开发]table表格组件>时隔了一个月,由于最近的项目比较坑,刚挖完坑,所以来总结性提出来几个组件弥补这次的空缺,首先是金额和 ...

  5. [js开源组件开发]query组件,获取url参数和form表单json格式

    query组件,获取url参数和form表单json格式 距离上次的组件[js开源组件开发]ajax分页组件一转眼过去了近二十天,或许我一周一组件的承诺有了质疑声,但其实我一直在做,只是没人看到……, ...

  6. Android自定义控件 开源组件SlidingMenu的项目集成

    在实际项目开发中,定制一个菜单,能让用户得到更好的用户体验,诚然菜单的样式各种各样,但是有一种菜单——滑动菜单,是被众多应用广泛使用的.关于这种滑动菜单的实现,我在前面的博文中也介绍了如何自定义去实现 ...

  7. FluentConsole是一个托管在github的C#开源组件

    FluentConsole是一个托管在github的C#开源组件 阅读目录 1.控制台能有啥滑头? 2.FluentConsole基本介绍 3.使用介绍 4.资源 从该系列的第一篇文章 .NET平台开 ...

  8. 微信开源的Android热补丁框架 Tinker

    前不久,微信开源了其Android热补丁框架Tinker,它的特别之处在于放在github.com/Tencent下面,是该账号下第一个正式的开源项目,可以看到腾讯对它的重视和认可. 早在6月份微信客 ...

  9. react-native开源组件react-native-wechat学习

    转载链接:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/react-native-open-source-components-r ...

随机推荐

  1. 修改host文件实现自定义域名和iis站点本地调试

    修改host文件实现自定义域名和iis站点本地调试 自定义域名:myhost.com windows版本:win7 iis版本:iis7.x vs版本:vs2010 现在开始动手设置了: 一.修改ho ...

  2. Ubuntu 查看默认软件安装位置

    tags: Linux 方法 1:在命令行输入:dpkg -L 软件包名: 方法 2:在/var/cache/apt/archives找的你安装程序的包,然后用gdebi-gtk+软件包名可以查看具体 ...

  3. white-space使用注意事项

    今天写移动端的时候有个地方需要横向滚动的功能,自然而然需要用到white-space这个属性了,但是试了一下发现没有效果,反复查找原因后,发现white-space是对inline-block起作用的 ...

  4. EasyUI中combogrid设置onSelect后 获取不到getSelecte问题解决

    $('#person').combogrid({ onSelect: function(index, item){ $('#dataForm').form('load', item); $(" ...

  5. android的布局-----LinearLayout(线性布局)

    学习导图(图片在网上下载) 知识点详解(演示效果方便组件没有设置id) (1)gravity和Layout_gravity android:gravity 属性是对该view中内容的限定.比如一个bu ...

  6. power key 啟動系統的相關電路

    Platform Qualcomm MSM8917 / 37 + PM8937(main PMIC) + PMI8940 Schematic Principles 當 power key 按下時, K ...

  7. uva 11491:Erasing and Winning(贪心)

    题意:给一个长n(n<10^5)位的数,删除d位,求删除后最大的数.(原数无前导0) 思路:从前往后扫,如果a[i] > a[i-1],则删除a[i-1].我暴力的用链表实现了…… #in ...

  8. C#根据经纬度获取物理地址

    废话不多说,直接上代码: 1.首先新建几个类,定义一些属性: public class BaiDuGeoCoding { public int Status { get; set; } public ...

  9. 深度学习_2_CNN

    Basic Conception: 感受野(Reception Field) 权值共享(shared weights) 池化,即降采样(sub-Sampling) 卷积核(kernel,filter) ...

  10. 牛客网 牛客小白月赛2 C.真真假假-String遍历比较

    C.真真假假 链接:https://www.nowcoder.com/acm/contest/86/C 这个题真的是无敌的水,但是自己写前面的string数组的时候,里面的这些头文件要用双引号(&qu ...