当前位置: 首页 > news >正文

从0开始弄一个面向OC数据库--终结篇

前言

我们从0开始封了一个面向OC模型的数据库就要结束了,开发工作其实在上一篇就做完了,之后做了一些小的优化以及代码的调整来发布这篇文章,先看一下我们最终形态。

  • 直接: 调用sqlite原生API操作数据库,没有中间框架。
  • 易用: 一行代码实现数据库增删查改操作。
  • 多元: 支持所有基本数据类型、集合类型以及自定义模型。
  • 智能: 一行代码,智能实现插入、更新、升级、迁移数据。
  • 强大: 0代码支持数组嵌套模型、嵌套字典,字典嵌套模型等相互嵌套。
  • 灵活: 支持多种查询、删除操作,支持使用sql语句查询、删除。
  • 还原: 存入数据库时为A模型,查询的数据一定还给你A模型。

我们支持的类型有

所有的基本数据类型(int,float),NSNumber,NSArray,NSMutableArray,NSDictionary,NSMutableDictionary,
UIImage,NSURL,UIColor,NSSet,NSRange,NSAttributedString,NSData,自定义模型,以及数组、字典、模型相互嵌套
复制代码

这篇文章,将全方位介绍我们数据库--CWDB以及如何使用!

架构

类名作用
CWModelProtocol.h需要遵守以及实现的协议方法(用户关注)
CWSqliteModelTool.h、CWSqliteModelTool.m本库操作数据库的所有API(用户关注)
CWDatabase.h、CWDatabase.m直接调用sqlite底层API的类
CWModelTool.h、CWModelTool.m处理模型的工具类
CWSqliteTableTool.h、CWSqliteTableTool.处理数据库表的工具类

在使用前,我们先模拟一个对应的使用场景,要解决什么问题,这个场景也是我们demo中的演示代码所展现的(你可以打开demo在Clasess目录下找到它)。

我们希望保存几所学校的资料到数据库。

  • 用一个类来表示学校的资料,资料有学校id,名字,整个学校的所有班级,最好的班级,最优秀的老师的资料。
  • 有对应类来表示班级的资料,班级里面有班级号,名称,班级的所有老师,班级的所有学生,班主任以及班长。
  • 又分别有两个类保存学生和老师的资料

以上的层级关系有模型嵌套数组嵌套模型的场景、模型嵌套模型再嵌套数据再嵌套模型的场景也就模型直接嵌套模型的场景。

然后我们使用工厂方法来快速构造各个模型,用来搭建整个学校

  • 首先,所有的学生都是身高168,年龄20,体重100,性格温和乖巧的女同学
  • 其次,所有的老师都是身高155,年龄28,体重100的御姐老师
  • 再次,我给每个班级添加5名松岛?同学,2名林?玲老师以及一位苍老师班主任
  • 最后,我任命我为全校唯一男人+校长,我在学校里面开设了2种专业总共4个班级,1个技巧班,3个声音班。保龄球玩得溜的关?琳同学获得最优学生,技巧班为最优班级,最好的老师当然是传授身教的苍老师

学校的结构设定好了之后~我们用代码构造一所所这样的梦想学院。。然后我们要使用我们的数据库将学校的资料保存起来。

How to use CWDB?

1、将CWDB拖进你的项目或者使用cocoapods(pod ‘CWDB’, '~> 1.5.0’),给项目添加sqlite3.0.tbd库,需要存储进数据库的模型导入CWModelProtocol.h头文件,然后遵守CWModelProtocol协议,实现下面这个方法返回对应的主键信息:

+ (NSString *)primaryKey {
    // 返回schoolId为主键
    return @"schoolId";
}
复制代码

2、为所欲为之为所欲为操作数据库

  • 插入或者更新数据
// 使用工厂方法创建的shool模型
CWSchool *school = [self cwSchoolWithID:9999 name:@"梦想学院"];
    
// 调用保存或者更新方法,uid为userId,对应数据库的名字,targetId为目标ID,与数据库表名相关,可以传nil。
BOOL result = [CWSqliteModelTool insertOrUpdateModel:school uid:nil targetId:nil];
复制代码

为什么要设置两个多余的参数uid与TargetId?为了迎合下面一些场景,如果你不关注,传nil即可

  • uid:在做IM的时候,一个手机APP可能登陆不同的账号,这个时候,我们希望将不同账号的信息,分为不同的数据库去保存,比如张三登陆了,我们以张三.db 新建一个数据库(之前没有数据库的情况下),李四登陆了,我们再以李四.db 新建一个数据库,他们的信息分别存在自己的数据库里,这样设计有什么好处?我们可以把各个用户的聊天记录以及相关信息分别存储,方便管理以及查询,比如你去银行存钱,你的钱一定是存在你的银行卡里面,而不会是你、我、他的钱都存在同一个银行卡里面,所以我们这里要传uid,用来分辨是哪一个用户的数据库。如果不传,会默认为CWDB公共数据库。
  • targetId:首先我们要说明,我们数据库的表名是以模型类型的名称来命名的。在大部分情况下,仅仅这样是没有问题的,但是,同样是在IM的场景下,比如我和张三聊天,那么我和张三的聊天记录会以Message的模型存在Message的表里面,如果我和李四聊天,那么我和李四的聊天记录也存在Message的表里面吗?这样数据库的数据会非常混乱,因为你可能会和更多的人聊天,那Message这个表会非常臃肿,所以我们引入targetId目标ID这一参数,我们的表名就会是《模型名称+targetId》,以张三为例,他的聊天记录表就是Message张三,李四就是Message李四。如果你的数据库里面一个模型只需要统一管理一个表,那么你传nil即可。

关于数据库升级以及数据库迁移,假设我存在数据库的数据为聊天记录Message,里面有10个成员变量,有一天,业务的提升,我要在Message里面多加一个成员变量,如新增一个成员变量用来标记是否是撤回的消息,这个时候由于数据库的表结构固定死了没这个字段,插入数据肯定是失败的,为了解决这个问题,我们将要进行数据库升级,并且要将之前的数据都保留下来,这个要怎么做呢?这里压根不需要你思考这个问题,我作为一个负责任的男人,我很负责任的告诉你,假如你的Message模型新增加了1个2个10个成员变量,你只管加,加了之后只管调用上面的方法存,数据的升级以及迁移我们默认会帮你完成!!!

  • 查询所有数据
// result内的元素为CWSchool的模型
NSArray *result = [CWSqliteModelTool queryAllModels:[CWSchool class] uid:nil targetId:nil];
复制代码

查询方法返回值是一个数组,这个数组里面的数据全部为CWSchool的模型,因为我们承诺过,保存的时候是模型A,查询出来的一定也是模型A。

  • 删除数据
CWSchool *school = [self cwSchoolWithID:9999 name:@"梦想学院"];
// 删除school数据
BOOL result = [CWSqliteModelTool deleteModel:school uid:nil targetId:nil];
复制代码

这个方法,会根据传进来的模型的主键值去找到数据表里面的数据删除。

我们的功能基本都在这了,除了还有一些条件查询与删除没写在这里。有人会问,数据库不是增删查改4个吗?怎么你只有3个,我们也实现了改的操作,只是我们把这个操作和增合并成了一个方法,也就是这里的第一个方法,我们会根据主键来判断数据库内是否存在对应的数据,如果存在,我们则进行更新操作,不存在则插入数据。

我们的演示代码对数据库操作提供了一个可视化的操作界面,大概是这样子

当然插入的数据与查询的数据是否对应从界面上是无法看出来的,你可以像我这样打一个断点查看

关于CWDB的更多用法,请转到github:CWDB查看或者看代码提供的API。。如果有不能满足你需求的场景或者有任何疑问,欢迎留言或者提issue,最终看在全校女同学的面子上 give me one star !!

如果你也想封装一个有很多女同学的数据库,但是没有资料学的话,可以前往我之前文章的传送门,每个功能的实现,我们都提供了非常详细的讲解:

从0开始弄一个面向OC数据库(一)

从0开始弄一个面向OC数据库(二)

从0开始弄一个面向OC数据库(三)

从0开始弄一个面向OC数据库(四)

从0开始弄一个面向OC数据库(五)

相关文章:

  • C++ Exercises(一)
  • restful+springmvc+mybatis+ webservice 分布式架构
  • 有歧义(AMBIGUOUS LAYOUT)的约束布局调试方法2
  • CSU-ACM2018寒假集训选拔-入门题
  • 云数据库 Redis 版功能特性
  • bootstrap和elementUI真的会冲突
  • LeetCode:26. Remove Duplicates from Sorted Array(Easy)
  • jvm 内存分配
  • 从Storm和Spark 学习流式实时分布式计算的设计
  • Nginx + Tomcat + HTTPS 配置原来不需要在 Tomcat 上启用 SSL 支持
  • 应用多级缓存模式支撑海量读服务
  • iOS 兼容多个有crash 收集机制的SDK
  • 37.3. HQL
  • 详细解析漏洞4个boom
  • HSRP、VRRP、ACL
  • [数据结构]链表的实现在PHP中
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Apache Zeppelin在Apache Trafodion上的可视化
  • express + mock 让前后台并行开发
  • golang中接口赋值与方法集
  • JavaScript DOM 10 - 滚动
  • JavaScript实现分页效果
  • JavaScript新鲜事·第5期
  • JavaScript异步流程控制的前世今生
  • js ES6 求数组的交集,并集,还有差集
  • Linux链接文件
  • spring boot下thymeleaf全局静态变量配置
  • Webpack 4 学习01(基础配置)
  • windows下如何用phpstorm同步测试服务器
  • 动态魔术使用DBMS_SQL
  • 由插件封装引出的一丢丢思考
  • 云栖大讲堂Java基础入门(三)- 阿里巴巴Java开发手册介绍
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • !$boo在php中什么意思,php前戏
  • #if 1...#endif
  • #stm32整理(一)flash读写
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)基于SSM多源异构数据关联技术构建智能校园-计算机毕设 64366
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)Mysql的优化设置
  • (转)一些感悟
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET Core 成都线下面基会拉开序幕
  • .net6使用Sejil可视化日志
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • [20170728]oracle保留字.txt
  • [20171101]rman to destination.txt
  • [ai笔记3] ai春晚观后感-谈谈ai与艺术
  • [ArcPy百科]第三节: Geometry信息中的空间参考解析
  • [C/C++] C/C++中数字与字符串之间的转换