WCDB背景


自己初次见到WCDB是微信开发团队公众号在今年五月份推送的一篇文章中(开发者团队的微信号上面图片中有,值得大家关注一下),那时候就说在筹备着WCDB的开源,觉得很是新奇,在两个多月前WCDB开源了!自己是最近才有时间看的WCDB,总结一下自己的理解和学习的东西,WCDB是微信团队开源的支持Android,也支持iOS,那当然也是会支持macOS的一个移动端数据库框架,FMDB估计做iOS的99.99%的都知道,就像Android开发中使用LitePal一样,都是在SQLite的基础上封装的移动数据库框架,WCDB是微信团队提供一个高效、易用、完整的移动端存储方案。 它包含三个模块:

1、WCDB-iOS/Mac

2、WCDB-Android

3、数据库损坏修复工具WCDBRepair

iOS 数据库框架对比分析


      一:关系型数据库,代表有CoreData、FMDB等

CoreData:微信团队在公众号的文章中对它的总结是这样:它是苹果内建框架,和Xcode深度结合,可以很方便进行ORM;但其上手学习成本较高,不容易掌握。稳定性也堪忧,很容易crash;多线程的支持也比较鸡肋。

FMDB:它基于SQLite封装,对于有SQLite和ObjC基础的开发者来说,简单易懂,可以直接上手;而缺点也正是在此,FMDB只是将SQLite的C接口封装成了ObjC接口,没有做太多别的优化,即所谓的胶水代码(Glue Code)。使用过程需要用大量的代码拼接SQL、拼装Object,并不方便

二:key-value数据库,代表有Realm、LevelDB、RocksDB等

微信团队对上面的总结是这样:因其在各平台封装、优化的优势,比较受移动开发者的欢迎。对于iOS开发者,key-value的实现直接易懂,可以像使用NSDictionary一样使用Realm。并且ORM彻底,省去了拼装Object的过程。但其对代码侵入性很强,Realm要求类继承RLMObject的基类。这对于单继承的ObjC,意味着不能再继承其他自定义的子类。同时,key-value数据库对较为复杂的查询场景也比较无力。

说说自己的理解:上面的像Realm、LevelDB、RocksDB等key - value 类型的这几个框架我都没有使用过,没有什么话语权,说说自己用过的,上面的CoreData和FMDB,我记得我去年有写过一篇博客,就这两者之间的区别等等的做过总结,有兴趣的可以去翻翻以前的,我也记得唐巧哥以前在他的公众号文章中也说过这事,就这两者之间还是支持FMDB,当然我相信CoreData苹果说不定哪天就让它变得受人们青睐,但当前可能还是做得不够吧,所以你这样看可能也就不难理解,一起为什么那么多人用FMDB,但确实也是有些场景中CoreData能做起来容易点的的不一定FMDB也容易,比如在两张表之间建立联系的时候,CoreData就会相对容易一点,所以,就像微信团队最后总结那那句一样:各个方案都有其独特的优势及劣势,没有最好的,只有最适合的。

你期盼的数据库框架是什么样子的?


下面这一段内容我不知道有多少伙伴在微信开发团队的公众号当中看到过,我自己看完下面这段话的时候,觉得总结的每一句话都是开发者的心声,也许看完这段话你也会和我一样,更加期盼的想去看看WCDB:

  • 高效;增删改查的高效是数据库最基本的要求。除此之外,我们还希望能够支持多个线程高并发地操作数据库,以应对微信频繁收发消息的场景。

  • 易用;这是微信开源的原则,也是WCDB的原则。SQLite本不是一个易用的组件:为了完成一个查询,往往我们需要写很多拼接字符串、组装Object的胶水代码。这些代码冗长繁杂,而且容易出错,我们希望组件能统一完成这些任务。

  • 完整;数据库操作是一个复杂的场景,我们希望数据库组件能完整覆盖各种场景。包括数据库损坏、监控统计、复杂的查询、反注入等。

初试WCDB- 理解ORM


下面的内容就从最基本的开始,从表的创建,到后面的CRUD的操作,以及再到后面一些高级的用法全都过一遍,在这当中涉及到的问题,有些可能会给连接大家可以自己去学习理解,有些我会说书我自己的理解,WCDB我们上路......

安装WCDB,在Wiki里面说的也比较完整,这里我们就不在多说,直接使用CocoaPods直接安装即可。

想理解WCDB需要先理解最基本的这个概念 ORM ,大家可以点进去看看微信给的使用说明,我们接着说:

在我们的Demo中,我们创建一个Message类,然后在这个类中声明我们需要的一些属性:

上面文件大家看到了这个Message+WCTTableCoding.h ,看着很像是我们常用的类别,其实就是,下面会说它的创建和作用,我们在我们的Message类中声明我们的属性,然后至于为什么要把.m 后缀改成.mm ,下面也会说,慢慢来。 下面就是我们为Message类建立ORM类字段绑定的过程:

1、定义该类遵守WCTTableCoding协议,可以在类声明上定义,也可以通过文件模版在category内定义(下面具体说)。这里推荐大家使用第二种,通过文件模板在category内定义,为什么要这样做,就是为了隔离Objective-C++代码,WCDB基于WINQ,引入了Objective-C++代码,所以对于引入了WCDB的源文件,都需要把后缀.m改为.mm,(这就是我们上面改后缀的原因)为减少影响范围,可以通过Objective-C的category特性将其隔离,达到只在model层使用Objective-C++编译,而不影响Controller和View。这一点在Wiki中是有提到的,

这样做的好处是不知道大家都有没有理解,这么说,要是你通过第一种方法,不通过category定义,而是选择了在类声明中写,这样的话Message.h 中就需要有宏WCDB_PROPERTY,这样你就在Message.h使用了WCDB的代码,当你把Message.h在其他Controller/View中引用的时候,那相应的Controller/View的.m就需要修改成.mm 。造成不必要的工作,但你用第二种方法写的时候,你就发现在Message.h中是没有任何的关于WCDB的代码的,后面你引用也不需要再去修改!希望大家理解这里。

在你项目中你集成了WCDB之后,你编译一下你的项目,你就可以看到上面我们说的模板文件,如下所示:

2、使用WCDB_PROPERTY宏在头文件声明需要绑定到数据库表的字段(也就是把你的表里面需要的字段在这里用这宏声明一次)

3、使用WCDB_IMPLEMENTATIO宏在类文件定义绑定到数据库表的类(把这个类绑定到数据库的表,你会在下面创建数据库的时候创建相应的表,表会和类绑定)

4、使用WCDB_SYNTHESIZE宏在类文件定义绑定到数据库表的类(第二步声明了表需要的字段,第三步绑定了表中的类,第四步就等于把表和字段绑定)

根据上面的步骤,就简单的完成了ORM的基本操作,想要了解更过的关于ORM宏的用法以及定义,还是查看Wiki文档:ORM使用教程

WCDB 初试 - CRUD


上面说完了ORM的操作,下面说说基本的数据库的创建以及CRUD的操作,在说下面之前,我们扯一点其他的,不知道会不会有人不知道该怎样去查看你建立的数据库内容,这里说推荐一个我自己一直在用的挺好用的工具 -- Navicat Premium ,你可以点击它去下载,提取密码是 e73y 。当然这不是我提供的,是简书同行提供的,谢谢无私奉献!

下载下来之后你点击安装的时候可能还需要密码:xclient.info

完了你打开,要是出现出损坏无法使用,打不开的情况,你需要设置:

注意: 要是你系统没有这个任何来源,终端命令: sudo spctl --master-disable

通过上面的操作,相信应该没什么问题了,接着简单一步带过怎样查看已有的数据库的:

左上角 Connection 选择 SQLite如下:

下面是正题,数据库的创建:

-(BOOL)creatDataBaseWithName:(NSString *)tableName{

    //获取沙盒根目录
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 文件路径
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"model.sqlite"];
NSLog(@"path = %@",filePath);
database = [[WCTDatabase alloc]initWithPath:filePath];
// 数据库加密
//NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];
//[database setCipherKey:password];
//测试数据库是否能够打开
if ([database canOpen]) { // WCDB大量使用延迟初始化(Lazy initialization)的方式管理对象,因此SQLite连接会在第一次被访问时被打开。开发者不需要手动打开数据库。
// 先判断表是不是已经存在
if ([database isOpened]) { if ([database isTableExists:tableName]) { NSLog(@"表已经存在");
return NO;
}else // 创建方法
return [database createTableAndIndexesOfName:tableName withClass:Message.class];
}
}
return NO;
}

下面是基本的增删查改的操作,这里写的一些都是最基本最基本的,下面再说两个基本的事务处理方法,然后再把CRUD操作的代码放出来,我们说的也知识基本的,要是想灵活应用还是得慢慢学,掌握它。

1、 block处理事务,顾名思义就是把我们的事务处理放在block当中,如下我们举的这个例子:

// 另一种事务处理方法Block
-(BOOL)insertMessageWithBlock{ BOOL commit = [database runTransaction:^BOOL{ BOOL ret = [self insertMessage];
if (ret) { return YES;
}else return NO;
} event:^(WCTTransactionEvent event) { NSLog(@"Event %d", event);
}];
return commit;
}

2、利用WCTTransaction来处理事务:

// WCTDatabase 事务操作,利用WCTTransaction
-(BOOL)insertMessageWithTransaction{ BOOL ret = [database beginTransaction];
ret = [self insertMessage];
if (ret) { [database commitTransaction]; }else [database rollbackTransaction]; return ret;
}

下面是我们写的简单的一个CRUD的操作的代码:

-(BOOL)insertMessage{

    //插入
Message *message = [[Message alloc] init];
message.localID = 1;
message.content = @"Hello, WCDB!";
message.createTime = [NSDate date];
message.modifiedTime = [NSDate date];
/*
INSERT INTO message(localID, content, createTime, modifiedTime)
VALUES(1, "Hello, WCDB!", 1496396165, 1496396165);
*/
return [database insertObject:message into:@"message"];
} -(BOOL)deleteMessage{ //删除
//DELETE FROM message WHERE localID>0;
return [database deleteObjectsFromTable:@"message" where:Message.localID > 0];
} -(BOOL)updataMessage{ //修改
//UPDATE message SET content="Hello, Wechat!";
Message *message = [[Message alloc] init];
message.content = @"Hello, Wechat!"; //下面这句在17号的时候和微信团队的人在学习群里面沟通过,这个方法确实是不存在的,使用教程应该会更新,要是没更新注意这个方法
//BOOL result = [database updateTable:@"message" onProperties:Message.content withObject:message];
return [database updateAllRowsInTable:@"message" onProperty:Message.content withObject:message];
} //查询
-(NSArray *)seleteMessage{ //SELECT * FROM message ORDER BY localID
NSArray<Message *> * message = [database getObjectsOfClass:Message.class fromTable:@"message" orderBy:Message.localID.order()]; return message; }

上面事务方面的暂时先说这么多,当然这方面的内容可以看具体的文档: 基础类、CRUD与Transaction

WCDB 其他


1、全局监控与错误处理

WCDB提供了对错误和性能的全局监控,可用于调试错误和性能。  也可以获取某个特定操作的错误信息。所有错误都以WCTError的形式出现。WCTError 就是继承自我们常见的NSError。

2、损坏修复

WCDB内建了修复工具,以应对数据库损坏,无法使用的情况。我们需要在数据库未损坏时,对数据库元信息定时进行备份,如下:

NSData *backupPassword = [@"MyBackupPassword" dataUsingEncoding:NSASCIIStringEncoding];
[database backupWithCipher:backupPassword];

注意:当检测到数据库损坏,即WCTError的type为WCTErrorTypeSQLite,code为11或26(SQLITE_CORRUPT或SQLITE_NOTADB)时,可以进行修复,下面是官方给出的代码示例:

//Since recovering is a long time operation, you'd better call it in sub-thread.
[view startLoading];
dispatch_async(DISPATCH_QUEUE_PRIORITY_BACKGROUND, ^{
WCTDatabase *recover = [[WCTDatabase alloc] initWithPath:recoverPath];
NSData *password = [@"MyPassword" dataUsingEncoding:NSASCIIStringEncoding];
NSData *backupPassword = [@"MyBackupPassword" dataUsingEncoding:NSASCIIStringEncoding];
int pageSize = 4096;//Default to 4096 on iOS and 1024 on macOS.
[database close:^{
[recover recoverFromPath:path
withPageSize:pageSize
backupCipher:cipher
databaseCipher:password];
}];
[view stopLoading];
});

3、性能数据

为了测试WCDB的性能数据,WCDB提供了benchmark,用于横向比较FMDB、纵向比较不同的参数配置,并可用于验证后续更多性能优化的效果。这里吧官方的文档给大家,有需要有兴趣的可以看看,这部分的内容以及下面从FMDB迁移到WCDB的内容我们会抓们整理出来,因为项目我也准备迁移到WCDB,等搞定会把相应新的分享出来。

4、从FMDB迁移到WCDB

这部分的内容上面提到自己在准备迁移到WCDB,所以就等迁移完成了会分享出心得。

上面的内容其实都是一些WCDB最基本的使用,也是希望WCDB大家都能掌握,既然是比FMDB好的存在我们也是肯定需要掌握的!

上面涉及到的Demo地址

从FMDB到WCDB、微信团队怎么说?的更多相关文章

  1. 微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅

    本文由微信开发团队工程是由“oneliang”原创发表于WeMobileDev公众号,内容稍有改动. 1.引言   Kotlin 是一个用于现代多平台应用的静态编程语言,由 JetBrains 开发( ...

  2. 微信团队分享:iOS版微信的高性能通用key-value组件技术实践

    本文来自微信开发团队guoling的技术分享. 1.前言 本文要分享的是iOS版微信内部正在推广和使用的一个高性能通用key-value 组件的技术实践过程,该组件在微信内部被命名为MMKV(以下简称 ...

  3. 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?

    本文来自微信开发团队yanyang的技术分享. 1.引言 相信大家都遇到过一段特殊文本可以让iOS设备所有app闪退的经历.前段时间大年初一,又出现某个印度语字符引起iOS11系统奔溃,所幸iOS版微 ...

  4. 微信团队原创分享:iOS版微信的内存监控系统技术实践

    本文来自微信开发团队yangyang的技术分享. 一.前言 FOOM(Foreground Out Of Memory),是指App在前台因消耗内存过多引起系统强杀.对用户而言,表现跟crash一样. ...

  5. 微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

    1.引言 岁月真是个养猪场,这几年,人胖了,微信代码也翻了. 记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟.如今用公司配的 17 年款 27-inch iMac 编译要接近半小时:偶 ...

  6. 微信开源组件WCDB漫谈及Demo

    代码地址如下:http://www.demodashi.com/demo/12422.html 前言 移动端的数据库选型一直是一个难题,直到前段时间看到了WeMobileDev(微信前端团队)放出了第 ...

  7. 如何开发一款堪比APP的微信小程序(腾讯内部团队分享)

    一夜之间,微信小程序刷爆了行业网站和朋友圈,小程序真的能如张小龙所说让用户"即用即走"吗? 其功能能和动辄几十兆安装文件的APP相比吗? 开发小程序,是不是意味着移动应用开发的一次 ...

  8. 【沙龙报名中】与微信&云开发官方团队零距离互动,揭秘爆款微信小游戏背后的技术!

    有人说 微信小程序游戏的百花齐放 活像十几年前的4399小游戏称霸互联网的景象 " 歪,斗地主吗,三缺二, 不用下app,小程序就能玩,我保证不抢地主让你抢!" ...... &q ...

  9. 【转】手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)

    1.引言 特别说明:本文内容仅用于即时通讯技术研究和学习之用,请勿用于非法用途.如本文内容有不妥之处,请联系JackJiang进行处理!   我司有关部门为了获取黑产群的动态,有同事潜伏在大量的黑产群 ...

随机推荐

  1. C#调用TSC条码打印机打印条码

    #region 调用TSC打印机打印条码 /// <summary> /// 调用TSC打印机打印条码 /// </summary> /// <param name=&q ...

  2. 如何在家自制LED灯?很简单,我来告诉你!

    首先LED分凸头.平头和凹头,当中的凹头是没无方向性. 做示宽灯这类晚间才运用的光源,用凹头就好,它没无方向性,可将整个反光碗照亮. 做转向灯等指示性的光源用,准绳上应该用凸头的,它是个聚光镜,投映的 ...

  3. App Extensions篇之Share Extension

    转载请注明出处:http://www.cnblogs.com/zhanggui/p/7119572.html 1.前言 这里主要是对App Extension的一些介绍以及详细给大家介绍一下Share ...

  4. input的文件上传图片

    <img id="headIMG" src="img/header_default.jpg"/> <input type="file ...

  5. Eclipse 迁移到Android studio

    步骤: 1.安装 android-studio-bundle-143.2915827-windows https://developer.android.com/studio/install.html ...

  6. 【Python3之pymysql模块】

    一.什么是 PyMySQL? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb. PyMySQL 遵循 Python 数据库 ...

  7. Windows10中“SQL Server 配置管理器”哪去了?

    SQL Server 配置管理器是一种工具,用于管理与 SQL Server 相关联的服务.配置 SQL Server 使用的网络协议以及从 SQL Server 客户端计算机管理网络连接配置.SQL ...

  8. MongoDB数据库文档操作

    前面的话 本文将详细介绍MongoDB数据库关于文档的增删改查 数据类型 在介绍文档操作之前,首先要了解MongoDB的数据类型 MongoDB支持许多数据类型,包括 1.字符串 - 这是用于存储数据 ...

  9. 关于abp中使用的sweetalert对话框组件的confirm确认对话框中的一个坑

    今天修改了一个功能,限制删除用户,在删除的时候不满足条件的时候提示用户原因,使用的sweet alert组件. abp框架前端集成了sweet alert 对http请求的error做了全局处理,我在 ...

  10. 处理文本,提取数据的脚本-主要就是用sed

    处理文本,提取数据的脚本 #! /bin/sh | sed 's/)<\/small><\/td><td>/\n/g' # 用换行符替换 # 删除带有分号的行 # ...