想到写这个的原因是我和我的一个朋友在写一个开源项目的时候,我负责了数据库的持久化存储部分,结果他看到了我的数据库数据存储结构之后直接傻眼了,因为个人比较简单粗暴,直接把一个数据Model归档成为二进制Data之后丢到了数据库,然后取出来也可以偷偷懒,解档就是一个模型Model啦,但是我的小伙伴不乐意了,把我批评了一顿,说我吧数据库的“检索”价值都给写没了,好吧,我承认当时我听得一脸懵逼,不过好像挺有道理?,不过按照他说的检索价值,我想的话应该就是把数据存储的更为清晰吧,那就要分更多的字段了【长长的SQL语句让我在角落瑟瑟发抖?】,唉,个人真的非常懒,想到这些就头疼,那么我们能不能用一个类根据Model属性生成SQL语句呢?答案是肯定的,接着往下看吧!

SQLite背景:【SQL(Structured Query Language)结构语言】SQLite是目前主流的嵌入式关系型数据库,其主要的特点的就是轻量级,跨平台,当前很多嵌入式操作系统都将其作为数据库的首先。它是基于C语言开发的数据库!所以我们需要通过hi用c语言语法进行数据库的操作和访问!

**思路:**SQL语句首先是建表,建表包含了字段名,表名,字段对应的存储类型,那么我们就要先来熟悉一下我们的七种基本数据类型以及那些常量类型到了数据库中是什么类型吧,这样才能和每一个字段对应上,既能够达到存储目的,又能节省空间

SQL数据库中的存储类型【比较多,但是请耐心看完,并不复杂】SQlite数据库存储类型

思路演变:我们既然想要用一个类来根据Model属性生成SQL,那么这个类肯定应该是普遍适用的,否则就没有多大意义了,那么我们肯定就要获取这个Model所有的属性以及属性对应的类型,然后根据这些属性名字来生成数据库中对应的字段,属性的类型经过处理之后变成数据库中的存储类型,很明显,我们又要用运行时了!

在了解了存储类型之后我们就要来真正的动刀了,首先我们要通过运行时来解析我们通常所用的数据类型在运行时中是怎么表示的;这里我就不多说了,直接贴方法,怎么根据运行时获取一个类所对应的属性和属性类型:

/**
根据要存储进入数据库中的类,获取该类的属性 以及 该类存储进入数据库后属性对应的 数据库存储类型
@param class 要存储的类
*/
- (void)disposePropertyWithClass:(Class)class
{
if (class && class != [NSObject class] && class != [MySqlStatementManager class]) {
unsigned int outCount = 0;
Ivar *ivars = class_copyIvarList(class, &outCount);
for (int i = 0 ; i < outCount; i ++ ) {
Ivar ivar = ivars[i];
//运行时获取属性名
NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
//去掉属性名开头中的下划线
if ([key rangeOfString:@"_"].location == 0) {
key = [key substringFromIndex:1];
}
//运行时获取类型
NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"@/:;()¥「」"、[]{}#%-*+=_\\|~<>$€^•’@#$%^&*()_+’\""];
type = [type stringByTrimmingCharactersInSet:set];
if (!self.propertyDic[type]) {
//如果属性类型不是七种基本数据类型,也不是int short 等常量类型,那么显示如下LOG提示
NSLog(@"数据库不支持%@类中为%@类型的%@属性存储,该属性数据将会丢失,请重新建立该类属性类型",NSStringFromClass(class),key,type);
}else{
// 将属性中的类型和数据库中的一些类型进行配对
NSString *sqlSaveType = self.propertyDic[type];
[self.propertyListDic setValue:sqlSaveType forKey:key];
}
}
free(ivars);
}
}
复制代码

这里用到了self.propertyDic  和  self.propertyListDic,解释一下: self.propertyDic  这个字典是用来将我们常用的所有类型按照:我们Model中各个属性用的类型【KEY】----各个属性应该对应的数据库存储类型【Value】先前就已经初始化好的一个固定不变的字典,意义就是根据我们用的类型来取到数据库中这个类型对应的存储类型 self.propertyListDic  这个字典是用来记录我们已经处理分析好的一些属性所应该对应的数据库存储类型,那么它最后的形式就是:我们Model中各个属性名称【KEY】----数据库中各个属性的存储类型【Value】

然后我分析之后我们的self.propertyDic应该是这样:

// 结合运行时获取model对应的属性类型 ( KEY ),然后这些类型将在数据库中以以下 (Value) 类型进行存储
- (NSDictionary *)propertyDic
{
if (_propertyDic == nil) {
_propertyDic = @{@"NSString" : @"varchar(1024)",
@"NSMutableString" : @"varchar(1024)",
@"NSArray" : @"blob",
@"NSMutableArray" : @"blob",
@"NSDictionary" : @"blob",
@"NSMutableDictionary" : @"blob",
@"NSData" : @"blob",
@"NSMutableData" : @"blob",
@"NSDate" : @"datetime",
@"NSNumber" : @"varchar(1024)",
@"c" : @"varchar(128)",    // 可能为BOOL 类型或者 char 类型
@"i" : @"int",    // Int 类型
@"s" : @"int",    // Short 类型
@"f" : @"float",    // Float 类型
@"d" : @"numeric",    // Double 类型
@"q" : @"int",    // Long 类型
@"B" : @"bit",    // iphone上BOOL类型运行时获取的类型名为 B, mac环境获取的是 ‘c’
@"" : @"",};
}
return _propertyDic;
}
复制代码

**解释说明:**可能已经有细心的小伙伴发现了,我的_propertyDic中设置的数组存储类型为blob【二进制大数据】,我知道这样做不妥,但是SQLite是不支持数组的存储的,而储存数组我认为的最佳方法是再建一张表,将这个数组用这一张表存起来,这其中又会涉及到数据库主键【PRIMARY KEY】的知识,取出数据时再通过联表查询才能取出来一个我们所需要的数据模型【不知道有没有对数据库很熟悉的小伙伴有不同的看法,欢迎来一起交流】,这还只是model中只有一个数组的情况下,如果数组中存储的数组,那就更尴尬了,可能一个Model要对应N张表联查才能取出来完整的数据,当然,数据库也是不支持OC字典存储的,所以剩下的场景大家自己脑补吧

**关于存储类型的结论:**综上情景的分析,为了偷懒【请原谅我如此直白】,我选择了直接将数组归档为二进制数据存储进入数据库?,有更好方法的欢迎评论区交流

那么继续吧,上面我们已经通过_propertyDic和_propertyListDic分析出了Model中存在的所有属性名称以及该属性应该在数据库中以何种类型存储,接下来就是生成SQL字符串了

因为SQL语句众多,这里我以建表的SQL为例,其他的大家可以自己去思考怎么生成SQL:

#pragma mark - 建表
- (NSString *)greatTableWithTableName:(NSString *)tableName andClass:(Class)modelClass
{[self disposePropertyWithClass:modelClass];__block NSString *greatSql = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS %@(",tableName];[self.propertyListDic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {greatSql = [NSString stringWithFormat:@"%@%@ %@,",greatSql,key, obj];}];greatSql = [greatSql substringToIndex:greatSql.length - 1];//补上结尾一个括号greatSql = [NSString stringWithFormat:@"%@)",greatSql];return greatSql;
}
复制代码

调用如下:

MySqlStatementManager *manger = [[MySqlStatementManager alloc] init];NSString *sql = [manger greatTableWithTableName:@"测试" andClass:[TestModel class]];NSLog(@"TestModel 对应的数据库 建表语句如下 %@",sql);
复制代码

转载于:https://juejin.im/post/5b2b05faf265da59aa2d8e32

用一个类根据Model属性生成SQL语句相关推荐

  1. 引用excel数据快速生成sql语句

    有时候我们需要把excel表格中的数据更新,或者插入到数据库表格中,这种往往是需要每一行写一个代码的,或者把excel导入数据库后再写SQL语句进行下一步的更新或者插入的处理. 现在介绍一个我摸索出来 ...

  2. android studio 自动生成sql语句,Android Studio Plugin 插件开发教程(三) —— 制作一个自动生成数据库代码的插件...

    项目源码 系列教程 插件介绍 本篇实战撸个自动生成安卓Sqlite数据库代码的插件,先演示下最终效果 db文件夹下的都是插件自动生成的,而MainActivity里面的代码是我提前写好的,用于实验插件 ...

  3. python sql语句生成_python Django 生成sql语句

    class TestModel(models.Model): Name=models.CharField(max_length=64,blank=True) >>> from dja ...

  4. 码匠 × OpenAI :快速生成 SQL 语句,提升开发效率!

    目录 使用 OpenAI 生成 SQL 码匠连接与集成 OpenAI 总结 关于码匠 在码匠中,编写 SQL 语句,并结合码匠一系列开箱即用的组件实现复杂的业务逻辑,是很常见的应用开发场景.然而,不同 ...

  5. 使用excel生成sql语句

    一.使用冒号配& 当需要生成的sql语句字符串少于255个字符的时候,可以使用冒号配合&读取读取单元格中的属性值 ="insert into table_test(code, ...

  6. 解放程序员双手!GPT-3自动生成SQL语句 | 代码开源

    金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI "无所不能"的GPT-3,现在又来解放程序员们的双手了. 像这样,只需用简单的英文问下GPT-3"上个月注册了 ...

  7. tp5循环查询语句_如何用Excel快速生成SQL语句,用过的人都说好

    Excel的公式自动生成想必大家都知道了,就是写好一个公式后直接往下拖,就可以将后面数据的公式自动生成. 今天我们就用这个功能来快速生成SQL语句. 导入Excel数据 Excel的数据有多种方式,这 ...

  8. 【项目经验】如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置

    如果想在mapper.xml文件中的一个标签中写多条sql语句,则需要在jdbc的配置文件中稍做配置: url=jdbc:mysql://127.0.0.1:3306/airipo?useUnicod ...

  9. 如何用Excel快速生成SQL语句,用过的人都说好

    导读:Excel的公式自动生成想必大家都知道了,就是写好一个公式后直接往下拖,就可以将后面数据的公式自动生成. 今天我们就用这个功能来快速生成SQL语句. 作者:丶平凡世界 来源:SQL数据库开发(I ...

最新文章

  1. 隔壁,阿里18k老测试员常用的 软件测试工具大全
  2. VS编译器如何单步调试
  3. 手写实现Spring(IOC、DI),SpringMVC基础功能
  4. 前端开发神器Sublime里如何设置JSlint
  5. 【深入Java虚拟机】之一:Java内存区域与内存溢出
  6. IDEA配置tomcat部署web项目时没有artifacts
  7. 学生宿舍管理信息系统软件测试,asp.net学生宿舍管理系统
  8. Appium基础 — APPium安装(二)
  9. php5.6 手册,php5.6手册下载
  10. Pytorch:图像风格迁移
  11. 2021-6-8集成电路可靠性试验项目、方法及标准汇总
  12. 极速解决“微信PC新版文件保存至MsgAttach”问题
  13. 计算机平均数据传输速率怎么算,如何计算总线数据传输速率
  14. 机器人摘果子看图写话_二年级摘苹果看图写话范例
  15. STG2Seq:多步乘车需求预测的时空图序列模型
  16. springcloud:config配置中心(多配置文件引入)
  17. 基于spaCy实现pytextrank对英文短语抽取
  18. 爬去微信小程序服务器代码,Python爬取微信小程序通用方法代码实例详解
  19. 苏亚星显示没有登录的服务器,苏亚星电子教室
  20. 推荐:在线面试实时编程工具——ShowMeBug

热门文章

  1. 【cocostudio】发布资源在Cocos2d-x中如何使用
  2. 直击微软MIX11 聚焦IE10、Silverlight5、WP7
  3. Emai乱码——解决的“迂回”战术
  4. Java SE、Java EE、Java ME基本区别
  5. python 13 常用模块 一
  6. ueditor百度编辑器中,多图上传后,图片顺序乱掉的处理方法
  7. win7安装virtualbox遇到的问题
  8. 发现个很有意思的angularjs +grunt 复习项目
  9. Sql结果导出为excel文件
  10. 豆瓣/name-?P=0/事件