热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微信开源组件WCDB漫谈及Demo

代码地址如下:http:www.demodashi.comdemo12422.html前言移动端的数据库选型一直是一个难题,直到前段时间看到了WeMob

代码地址如下:
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
      WCDB458000
      FMDB161000
  • 易用 WCDB支持一句代码即可将数据取出并组合为object
    • WINQ(WCDB语言集成查询):通过WINQ,开发者无须为了拼接SQL的字符串而写一大坨胶水代码。

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

    • 像这样

      [database getObjectsOfClass:WCTSampleConvenient.classfromTable: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的功能。如下

dDqU6.md.jpg

dDOMd.md.jpg

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

对于一个已有的ObjC类,

  • 引用WCDB框架头文件#import ,并定义类遵循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 = [database getObjectsOfClass:Person.class fromTable:TABLE_WCDB_NAME orderBy:Person.localID.order()];

Transaction

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

dDH3J.md.jpg

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

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

dDEbr.md.jpg

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

WINQ

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

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

原理

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

数据库修复

  • 官方的Dump恢复方案
    • 遍历sqlite_master表&#xff0c;将未损坏的表和已损坏的前半部分读取出来将dump 出来的SQL语句逐行执行&#xff0c;最终可以得到一个等效的新DB
      功率约为30%。
    • 第一页就损坏后续无法读取
  • 备份恢复方案
    • COPY
    • 在DB完好的时候执行.dump
    • Backup API&#xff1a; SQLite自身提供的一套备份机制&#xff0c;按 Page 为单位复制到新 DB&#xff0c; 支持热备份。
    • 最终选择Dump &#43; 压缩&#xff0c;恢复成功率达到72%
  • 解析B-tree恢复方案&#xff08;RepairKit&#xff09;
    • 成功率约为78%
  • 不同方案的组合
    • RepairKit 尝试恢复最新数据
    • 备份恢复 遇到错误填补漏缺
    • Dump 最后的尝试

For Android

  • 基本功能
    • 基于SQLCipher的数据库加密
    • 使用连接池实现并发读写
    • 内建 Repair Kit 可用于修复损坏数据
    • 针对占用空间大小优化的数据库备份/恢复功能
    • 日志输出重定向以及性能跟踪接口
    • 内建用于全文搜索的 mmicu FTS3/4 分词器
  • 接入与迁移
    • WCDB for Android 可通过 Maven 或 AAR 包引用&#xff0c;API 接口与 Android SDK 非常相近&#xff0c; 所以将已有的 App 迁移到 WCDB 是相当容易的。
    • Android 接入与迁移
  • 数据库修复
    • Android 数据库修复
  • 从源码编译
    • 你可以使用预编译的依赖库&#xff08;OpenSSL crypto 和 SQLCipher&#xff09;来编译 WCDB for Android&#xff0c; 使用 Gradle 或 Android Studio 皆可。Android Studio 请导入 android 目录作为 Root Project。
    • 编译 WCDB 需要安装 Android NDK r11c 或以上&#xff0c;并在 android/local.properties 上配置好 SDK 与 NDK 路径。Android Studio 一般会帮你配置好。
    • 如果你需要自己编译 OpenSSL 等依赖项&#xff0c;你需要一个 Bash 环境&#xff08;Windows 可以安装 Cygwin 或 MSys&#xff09;、target 为本机的 C 编译器&#xff08;如 GCC&#xff09;、Perl 5 以及 Tcl。之后执行下面命令即可编译依赖项。

参考资料

微信移动端数据库组件WCDB系列&#xff08;一&#xff09;-iOS基础篇

微信移动端数据库组件WCDB系列&#xff08;二&#xff09; — 数据库修复三板斧

微信移动端数据库组件WCDB系列&#xff08;三&#xff09; — WINQ原理篇

微信移动数据库组件WCDB&#xff08;四&#xff09; — Android 特性篇微信开源组件WCDB漫谈及Demo

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

注&#xff1a;本文著作权归作者&#xff0c;由demo大师代发&#xff0c;拒绝转载&#xff0c;转载需要作者授权




推荐阅读
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Echarts图表重复加载、axis重复多次请求问题解决记录
    文章目录1.需求描述2.问题描述正常状态:问题状态:3.解决方法1.需求描述使用Echats实现了一个中国地图:通过选择查询周期&#x ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
author-avatar
骏马奔腾09
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有