iOS Sqlite数据库的使用
总体内容
1、sqlite基本操作封装
2、动态建表-基本创建
3、动态建表-忽略字段
4、动态更新表-迁移数据
5、保存/更新模型
6、删除模型
7、查询模型
8、模型中-字典/数组属性处理
9、存在问题的优化方案
10、上面所有步骤组合起来的JKSqliteKit
的使用
一、sqlite基本操作封装
-
1.1、创建项目,导入
创建项目,导入 `libsqlite3.0.tbd`libsqlite3.0.tbd
-
1.2、打开数据库
-
<1>、获取数据库的名字
NSString *sqliteName = @"jk_common.sqlite"; if (sqliteName.length != 0) { sqliteName = [NSString stringWithFormat:@"jk_%@.sqlite",uid]; }
提示:数据库的名字我们采取 用户机制,操作数据库,共同的数据库,也就是未登录状态,统一使用
jk_common.sqlite
数据库,登陆后,根据用户的id创建对应的数据库:jk_(用户id).sqlite
-
<2>、对应的路径(我们把对一个的数据库放到了
/Library/Caches
下)NSString *sqlitePath = [JKSqliteCachePath stringByAppendingPathComponent:sqliteName];
提示:JKSqliteCachePath 是一个宏:
#define JKSqliteCachePath [NSHomeDirectory() stringByAppendingPathComponent:@"/Library/Caches"]
-
<3>、打开数据库,不存在的情况下自动创建
sqlite3 *ppDb = nil; if (sqlite3_open(sqlitePath.UTF8String, &ppDb) != SQLITE_OK) { // 打开数据库失败 return NO; }
-
-
1.3、关闭数据库
// 关闭数据库 sqlite3_close(ppDb);
-
1.4、执行语句( DDL
(增、删、改)
、DDL(表格操作):返回执行结果)// 执行sql语句 /** 第1个参数:数据库对象 第2个参数:sql语句 第3个参数:查询时候用到的一个结果集闭包 第4个参数:用不到 第5个参数:用不到 */ BOOL result = sqlite3_exec(ppDb, sql.UTF8String, nil, nil, nil) == SQLITE_OK;
-
1.5、查询语句(DQL:返回结果集),核心代码如下
/** 查询数据 @param sql sql 语句 @param uid 用户的id @return 字典组成的数组,每一个字典都是一行记录 */ +(NSMutableArray <NSMutableDictionary *>*)querySql:(NSString *)sql witUid:(NSString *)uid{ // 1.打开数据库 If (![self openDB:uid]) { NSLog(@"打开失败"); return nil; } // 准备语句,预处理语句 // 2.创建准备语句 /** 第1个参数:一个已经打开的数据库对象 第2个参数:sql语句 第3个参数:参数2中取出多少字节的长度,-1 自动计算,\0停止取出 第4个参数:准备语句 第5个参数:通过参数3,取出参数2的长度字节之后,剩下的字符串 */ sqlite3_stmt *ppStmt = nil; if (sqlite3_prepare_v2(ppDb, sql.UTF8String, -1, &ppStmt, nil) != SQLITE_OK) { NSLog(@"准备语句编译失败"); return nil; } // 2.绑定数据(可以有 ? 的省略) // 3.执行 // 大数组 : SQLITE_ROW代表数据的不断的向下查找 NSMutableArray *rowDicArray = [NSMutableArray array]; while (sqlite3_step(ppStmt) == SQLITE_ROW) { // 一行记录 -> 字典 // 记录值的字典 NSMutableDictionary *rowDictionary = [NSMutableDictionary dictionary]; // 3.1、获取所有列的个数 int columnCount = sqlite3_column_count(ppStmt); // 3.2、遍历所有的列 for (int i=0; i<columnCount; i++) { // 3.2.1、获取所有列的名字,也就是表中字段的名字 // C语言的字符串 const char *columnNameC = sqlite3_column_name(ppStmt, i); // 把 C 语言字符串转为 OC NSString *columnName = [NSString stringWithUTF8String:columnNameC]; // 3.2.2、获取列值 // 不同列的类型,使用不同的函数,进行获取值 // 3.2.2.1、获取列的类型 int type = sqlite3_column_type(ppStmt, i); /** 我们使用的是 SQLite3,所以是:SQLITE3_TEXT SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT, not SQLITE_INTEGER 1 SQLITE_FLOAT 2 SQLITE3_TEXT 3 SQLITE_BLOB 4 SQLITE_NULL 5 */ // 3.2.2.2、根据列的类型,使用不同的函数,获取列的值 id value = nil; switch (type) { case SQLITE_INTEGER: value = @(sqlite3_column_int(ppStmt,i)); break; case SQLITE_FLOAT: value = @(sqlite3_column_double(ppStmt, i)); break; case SQLITE3_TEXT: value = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(ppStmt, i)]; break; case SQLITE_BLOB: value = CFBridgingRelease(sqlite3_column_blob(ppStmt, i)); break; case SQLITE_NULL: value = @""; break; default: break; } // 字典填值 [rowDictionary setValue:value forKey:columnName]; } // 每一个添加到数组中 [rowDicArray addObject:rowDictionary]; } // 4.重置(省略) // 5.释放资源 sqlite3_finalize(ppStmt); // 6.关闭数据库 [self closeDB]; return rowDicArray; }
二、sqlite 数据库动态建表-基本创建
-
2.1、当我们建立一个model模型的时候,一类名为表名,以成员变量的名字为字段名,成员变量的类型为 sqlite 的类型,从而动态的创建表,如下的模型
Student模型 -
2.2、创建表的 sql 语句合成
目标sql语句:
create table if not exists 表名(字段1 字段1类型(约束),字段2 字段2类型(约束),字段3 字段3类型(约束),.....,primary(字段))
-
<1>、获取表名
+(NSString *)tableName:(Class)cls{ // 把类转化为类名的字符串 return NSStringFromClass(cls); }
-
<2>、判断模型里面是否有主键(定义一个协议,让用户设置主键),协议是:
JKSqliteProtocol.h
里面if (![cls respondsToSelector:@selector(primaryKey)]) { NSLog(@"请设置模型里面的主键,遵守协议,实现+(NSString *)primaryKey;,d从而得到主键信息"); return NO; }
-
<3>、拼接字段与对应类型的字符串(如:
字段1 字段1类型(约束),字段2 字段2类型(约束),字段3 字段3类型(约束),.....,
),可以参考demo里面的JKSqliteModelTool
类提示:技术点是:利用runtime获取一个类的成员变量,根据成员变量不同的类型转换成sqlite里面的类型,再把它们合成sql语句类里面字段的 语句
获取一个模型里面所有的字段名字,以及类型
+(NSDictionary *)classIvarNameTypeDictionary:(Class)cls{ NSMutableDictionary *nameTypeDictionary = [NSMutableDictionary dictionary]; // 获取所有的成员变量 unsigned int outCount = 0; Ivar *varList = class_copyIvarList(cls, &outCount); for (int i = 0; i<outCount; ++i) { Ivar ivar = varList[I]; // 1.获取成员变量名字 NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)]; if ([ivarName hasPrefix:@"_"]) { // 把 _ 去掉,读取后面的 ivarName = [ivarName substringFromIndex:1]; } // 2.获取成员变量类型 NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)]; // 把包含 @\" 的去掉,如 "@\"NSString\"";-> NSString ivarType = [ivarType stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"@\""]]; NSLog(@"ivarType=%@",ivarType); // 3.成员变量的类型可能重复,成员变量的名字不会重复,所以以成员变量的名字为key [nameTypeDictionary setValue:ivarType forKey:ivarName]; } return nameTypeDictionary; }
获取一个模型里面所有的字段名字,以及类型(类型转换为sqlite里面的类型)
+(NSDictionary *)classIvarNameSqliteTypeDictionary:(Class)cls{ NSMutableDictionary *dict = [[self classIvarNameTypeDictionary:cls] mutableCopy]; NSDictionary *typeDict = [self switchOCTypeToSqliteTypeDict]; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL * _Nonnull stop) { // 字典 dict[key] = typeDict[obj]; }]; return dict; }
把上面两个方法合成的字段组合成sql语句里面的 字段
+(NSString *)columnNamesAndTypesStr:(Class)cls{ NSDictionary *dict = [self classIvarNameSqliteTypeDictionary:cls]; NSMutableArray *result = [NSMutableArray array]; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL * _Nonnull stop) { [result addObject:[NSString stringWithFormat:@"%@ %@",key,obj]]; }]; return [result componentsJoinedByString:@","]; }
-
三、动态建表-忽略字段
-
3.1、在定义的协议里面设置,必须实现的方法和可以不用实现的方法,如下:
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @protocol JKSqliteProtocol <NSObject> // 主键 @required // 必须实现的方法 +(NSString *)primaryKey; @optional // 可以不用实现的方法 +(NSArray *)ignoreColumnNames; @end NS_ASSUME_NONNULL_END
-
3.2、模型类里面实现协议方法,以demo里面的
Student
类为例#import "Student.h" @implementation Student +(NSString *)primaryKey{ return @"studentNumber"; } // 实现要在动态创建表的时候要忽略的字段 +(NSArray *)ignoreColumnNames{ return @[@"testName"]; } @end
-
3.3、在动态创建表创建表的方法里面实现过滤忽略字段
在
JKSqliteModel
里面的+(NSDictionary *)classIvarNameTypeDictionary:(Class)cls
方法类里面-
先判断模型有没有实现忽略方法,有的话取出来
NSArray *ignoreNamesArray = nil; if ([cls respondsToSelector:@selector(ignoreColumnNames)]) { ignoreNamesArray = [cls ignoreColumnNames]; }
-
判断遍历的成员变量是否包含在数组里面,在里面就
continue
过滤// 1.1、查看有没有忽略字段,如果有就不去创建(根据自己模型里面是否设置了忽略字段) if ([ignoreNamesArray containsObject:ivarName]) { continue; }
-
四、动态更新表-迁移数据
-
4.1、检测表格是否需要更新(在类
JKSqliteTableTool
里面)
判断是否更新表格的依据:获取model
(模型)所有的成员变量名数组与表格里面所有的字段组成的数据进行对比,前提是二者的数组都进行过排序,利用数组isEqualToArray
判断,核心代码如下+(BOOL)isUpdateTable:(Class)cls uid:(NSString *)uid{ // 1.获取模型里面的所有成员变量的名字 NSArray *modelNames = [JKSqliteModel allTableSortedIvarNames:cls]; // 2.获取uid对应数据库里面对应表的字段数组 NSArray *tableNames = [JKSqliteTableTool tableColumnNames:cls uid:uid]; // 3.判断两个数组是否相等,返回响应的结果,取反:相等不需要更新,不相等才需要去更新 return ![modelNames isEqualToArray:tableNames]; }
提示:上面两个数组的获取都很有学习意义,建议看着demo读这篇博客
-
4.2、动态迁移数据
思路:由于sqlite 是阉割版的,虽然sql语句有删除字段的操作,但是在xcode中不奏效,只有采用如下的方法来解决表更新字段的问题,代码在JKSqliteModelTool
的+(BOOL)updateTable:(Class)cls uid:(NSString *)uid
里面- <1>、根据新模型创建临时表
- <2>、把就表中的主键数据插入临时表
- <3>、临时表中的字段有在旧表中的,根据两表主键相等把旧表数据导入临时表
- <4>、删除旧表,并把临时表名改为旧表名
提示:上面的方法其实就是在用户无察觉的情况下完成了偷梁换柱
-
4.3、字段改名
-
通过协议获取改名的映射字典
@optional // 更新字段: 新字段名字 到 旧字段名字 的映射表(字典的key是新字段,字典的value是旧字段) +(NSDictionary *)updateFieldNewNameReplaceOldName;
-
在模型里面实现方法(用
studentAge1
字段替换studentAge
字段)+(NSDictionary *)updateFieldNewNameReplaceOldName{ return @{@"studentAge1":@"studentAge"}; }
-
迁移数据时, 进行过滤
// 获取更名字典 NSDictionary *newNameReplaceOldNameDict = @{}; if ([cls respondsToSelector:@selector(updateFieldNewNameReplaceOldName)]) { newNameReplaceOldNameDict = [cls updateFieldNewNameReplaceOldName]; }
提示:在执行 动态迁移数据 这块会有很多的 sql 语句,为了保证都执行成功才是成功,我们可以用 事务 来解决,具体的代码可以看
JKSqliteDatabase
类,对数据库的操作 -
五、保存/更新模型
-
5.1、思路分析
要保存一个模型的数据:1、要先判断这个模型对应的表是否存在;2、不存在的话创建表,存在就判断是否需要更表是否需要更新;3、按照模型主键查看当前主键下的数据是否存在,存在的话就根据主键值更新数据,不存在的话就插入数据 -
5.2、具体的步骤代码如下,具体的可以参考JKSqliteModelTool里面的
+(BOOL)saveOrUpdateModel:(id)model uid:(NSString *)uid;
方法,核心代码如下+(BOOL)saveOrUpdateModel:(id)model uid:(NSString *)uid{ // 用户在使用的过程中直接调用这个方法,来保存模型 Class cls = [model class]; // 1、判断表格是否存在,不存在就去创建 if (![JKSqliteTableTool isTableExists:cls uid:uid]) { // 创建表格 if (![self createTable:cls uid:uid]) { // 创建失败 return NO; } } // 2、检测表格是否需要更新,需要则更新,不需要则不更新 if ([self isUpdateTable:cls uid:uid]) { // 更新表格 [self updateTable:cls uid:uid]; } // 3、判断记录是否存在,按照主键的值查询,如果能查询到,那么久更新数据,如果查询不到,就把这条数据插入 // 获取表名 NSString *tableName = [JKSqliteModel tableName:cls]; // 判断模型里面是否有主键 if (![cls respondsToSelector:@selector(primaryKey)]) { NSLog(@"请设置模型里面的主键,遵守协议,实现+(NSString *)primaryKey;,d从而得到主键信息"); return NO; } // 拿到主键 NSString *primaryKey = [cls primaryKey]; // 模型里面主键的值 id primaryKeyValue = [model valueForKeyPath:primaryKey]; // 创建sql语句 NSString *checkPrimaryKeySql = [NSString stringWithFormat:@"select * from %@ where %@ = %@",tableName,primaryKey,primaryKeyValue]; // 进行查询 // 获取表中所有的字段(下面的方法获取的是字典,我们取其键) NSArray *columnNames = [JKSqliteModel classIvarNameTypeDictionary:cls].allKeys; // 获取模型里面所有的值数组 NSMutableArray *columnNameValues = [NSMutableArray array]; for (NSString *columnName in columnNames) { id columnNameValue = [model valueForKeyPath:columnName]; [columnNameValues addObject:columnNameValue]; } // 把字段和值拼接生成 字段 = 值 字符的数组 NSInteger count = columnNames.count; NSMutableArray *setValueArray = [NSMutableArray array]; for (int i = 0; i<count; i++) { NSString *name = columnNames[I]; id value = columnNameValues[I]; NSString *setStr = [NSString stringWithFormat:@"%@ = '%@'",name,value]; [setValueArray addObject:setStr]; } NSString *execSql = @""; if ([JKSqliteDatabase querySql:checkPrimaryKeySql witUid:uid].count > 0) { // update 表名 set 字段1=值 字段2=值.... where 主键名 = 对应的主键值;" // 查询的结果大于0说明表中有这条数据,进行数据更新 // 获取 更新的 sql 语句 execSql = [NSString stringWithFormat:@"update %@ set %@ where %@ = %@;",tableName,[setValueArray componentsJoinedByString:@","],primaryKey,primaryKeyValue]; }else{ // 不存在数据,进行记录的插入操作 // 提示这里 insert into %@(%@) values('%@');,其中的value 要是: 'value1','value2','value2'这样的格式 execSql = [NSString stringWithFormat:@"insert into %@(%@) values('%@');",tableName,[columnNames componentsJoinedByString:@","],[columnNameValues componentsJoinedByString:@"','"]]; } return [JKSqliteDatabase deal:execSql witUid:uid]; }
六、删除模型
-
6.1、删除整个模型,也是删除对应用户数据库中的一个表
/** 删除模型,也是删除模型中的全部数据,可以说是删除整个表 */ +(BOOL)deleteModel:(id)model uid:(NSString *)uid{ Class cls = [model class]; // 获取表名 NSString *tableName = [JKSqliteModel tableName:cls]; if (![JKSqliteTableTool isTableExists:cls uid:uid]) { // 表不存在默认删除成功 return YES; } // 组建删除表的语句 NSString *deleteSql = [NSString stringWithFormat:@"drop table %@;",tableName]; return [JKSqliteDatabase deal:deleteSql witUid:uid]; }
-
6.2、根据主键删除模型中的某一条数据
/** 删除模型里面的一条记录 */ +(BOOL)deleteRecordingModel:(id)model uid:(NSString *)uid{ Class cls = [model class]; // 判断模型里面是否有主键 if (![cls respondsToSelector:@selector(primaryKey)]) { NSLog(@"请设置模型里面的主键,遵守协议,实现+(NSString *)primaryKey;,d从而得到主键信息"); return NO; } // 拿到主键 NSString *primaryKey = [cls primaryKey]; // 模型里面主键的值 id primaryKeyValue = [model valueForKeyPath:primaryKey]; // 获取表名 NSString *tableName = [JKSqliteModel tableName:cls]; NSString *deleteSql = [NSString stringWithFormat:@"delete from %@ where %@ = %@;",tableName,primaryKey,primaryKeyValue]; return [JKSqliteDatabase deal:deleteSql witUid:uid]; }
-
6.3、根据用户的条件删除表中的记录(根据条件删除)
+(BOOL)deleteModel:(id)model whereStr:(NSString *)condition uid:(NSString *)uid{ Class cls = [model class]; // 获取表名 NSString *tableName = [JKSqliteModel tableName:cls]; // 条件小于0直接返回 if (!(condition.length > 0)) { return NO; } // 组建删除表的语句 NSString *deleteSql = [NSString stringWithFormat:@"delete from %@ where %@;",tableName,condition]; return [JKSqliteDatabase deal:deleteSql witUid:uid]; }
提示:在使用这个条件的方法,要求开发者会 sql 语句,要求高一些
七、查询模型
-
7.1、查询模型中所有的数据
/** 查询模型中所有的数据 */ +(NSArray *)queryAllDataModel:(Class)cls uid:(NSString *)uid{ // 1.查询前序 // 获取表名 NSString *tableName = [JKSqliteModel tableName:cls]; // 组合查询语句 NSString *querySql = [NSString stringWithFormat:@"select * from %@",tableName]; // 2.执行查询 key value // 模型的属性名称 和 属性值 NSArray <NSDictionary *>*results = [JKSqliteDatabase querySql:querySql witUid:uid]; // 3.处理查询结果集 -> 模型数组 return [self parseResults:results withClass:cls]; }
-
7.2、 根据条件来查询模型里面的部分数据
+(BOOL)queryDataModel:(Class)cls whereStr:(NSString *)condition uid:(NSString *)uid{ // 1.查询前序 // 获取表名 NSString *tableName = [JKSqliteModel tableName:cls]; // 组合查询语句 NSString *querySql = [NSString stringWithFormat:@"select * from %@ where %@;",tableName,condition]; // 2.执行查询 key value // 模型的属性名称 和 属性值 NSArray <NSDictionary *>*results = [JKSqliteDatabase querySql:querySql witUid:uid]; // 3.处理查询结果集 -> 模型数组 return [self parseResults:results withClass:cls]; }
八、模型中-字典/数组属性处理
-
8.1、分析:对于字典和数组存储数据库,我们组要把它们先转为 NSData,再转为NSStrinig;在取值的时候,我们进行反序列化,根据模型里面字段的类型,把数据库中的数组或者字典的字符串值转化为NSData,再反序列化为对应的类型,从而使用 KVC 赋值给对应的key
-
8.2、字典和数组存储数据库的核心代码(完整代码在
JKSqliteModelTool
里面的+(BOOL)saveOrUpdateModel:(id)model uid:(NSString *)uid
方法中)// 获取表中所有的字段(下面的方法获取的是字典,我们取其键) NSArray *columnNames = [JKSqliteModel classIvarNameTypeDictionary:cls].allKeys; // 获取模型里面所有的值数组 NSMutableArray *columnNameValues = [NSMutableArray array]; for (NSString *columnName in columnNames) { id columnNameValue = [model valueForKeyPath:columnName]; // 判断类型是不是数组或者字典 if ([columnNameValue isKindOfClass:[NSArray class]] || [columnNameValue isKindOfClass:[NSDictionary class]]) { // 在这里我们把数组或者字典处理成一个字符串,才能正确的保存到数据库里面去 // 字典/数组 -> NSData ->NSString NSData *data = [NSJSONSerialization dataWithJSONObject:columnNameValue options:NSJSONWritingPrettyPrinted error:nil]; columnNameValue = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; } [columnNameValues addObject:columnNameValue]; }
注意:上面在可变与不可变的处理,可变的数组或者字典是继承于不可变的
-
8.3、字典和数组从数据库读取的核心代码(具体的代码请看
JKSqliteModelTool
里面的+ (NSArray *)parseResults:(NSArray <NSDictionary *>*)results withClass:(Class)cls
方法)NSString *type = nameTypeDic[key]; // id resultValue = obj; if ([type isEqualToString:@"NSArray"] || [type isEqualToString:@"NSDictionary"]) { // 字符串 -> NSData -> 相应的类型 NSData *data = [obj dataUsingEncoding:NSUTF8StringEncoding]; /** NSJSONReadingMutableContainers = (1UL << 0), 可变的 NSJSONReadingMutableLeaves = (1UL << 1), 可变的的类型里面还有可变的 NSJSONReadingAllowFragments = kNilOptions 不可变 */ resultValue = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; }else if ([type isEqualToString:@"NSMutableArray"] || [type isEqualToString:@"NSMutableDictionary"]){ // 字符串 -> NSData -> 相应的类型 NSData *data = [obj dataUsingEncoding:NSUTF8StringEncoding]; resultValue = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; } [model setValue:resultValue forKey:key];
注意:上面在可变与不可变的处理上
9、存在问题-优化方案
-
9.1、存在的问题一:无法创建复杂的表格, 比如添加约束等行为,如下的创建表,很多的字段,后面都是有一定的约束以及一些默认的值
create table students( id int unsigned primary key auto_increment not null, name varchar(20) default '', age tinyint unsigned default 0, height decimal(5,2), gender enum('男','女','人妖','保密') default "保密", cls_id int unsigned default 0 );
解决办法:用协议解决,告诉我们每个字段需要加什么约束,我们在创建表或者更新字段的时候 拼接在相应的字段后面
-
9.2、存在的问题二:无法进行复杂的查询, 比如多表联查
解决办法:暴漏完整的sql语句来执行
10、上面所有步骤组合起来的JKSqliteKit
的使用
-
10.1、创建项目,导入
libsqlite3.0.tbd
,步骤和1.1
一样 -
10.2、主要的类
- JKSqliteDatabase : 数据库的操作
- JKSqliteModel :模型的操作
- JKSqliteModelTool : 操作模型的类
- JKSqliteTableTool : 有关表的操作
- JKSqliteProtocol :存放协议的内容
-
10.3、具体使用
-
<1>、创建一个
Person
类继承于NSObject
,设置如下四个属性#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface Person : NSObject /** 人的ID */ @property(nonatomic,assign) int personID; /** 人的名字 */ @property(nonatomic,strong) NSString *personName; /** 人的年龄 */ @property(nonatomic,strong) NSString *personAge; /** 人的身高 */ @property(nonatomic,strong) NSString *personHeight; /** 人的爱好 */ @property(nonatomic,strong) NSArray *personLikes; @end NS_ASSUME_NONNULL_END
-
<2>、导入协议:
#import "JKSqliteProtocol.h"
,设置personID
(人的ID)为主键,主键是必须设置的,在协议里面我们设置了@required
// 导入协议 #import "JKSqliteProtocol.h" // 设置主键 +(NSString *)primaryKey{ return @"personID"; }
-
<3>、找个控制器,创建一个
Person
模型,模型属性赋值,存入数据库,我们采用的用户机制,不同的用户登录app,对应不同的数据库,格式是:jk_用户的ID.sqlite
,未登录是:jk_common.sqlite
,存在于 沙盒的/Library/Caches
下Person *person = [[Person alloc]init]; person.personID = 2; person.personName = @"王小二"; person.personAge = 29; person.personHeight = 178; person. personLikes =@["篮球",@"足球"]; BOOL result = [JKSqliteModelTool saveOrUpdateModel:person uid:@"1"]; if(result){ // 保存成功 }else{ // 保存失败 }
-
<4>、取出模型使用
NSArray *resultArray = [JKSqliteModelTool queryAllDataModel:NSClassFromString(@"Person") uid:@"1"]; NSLog(@"resultArray=%@",resultArray); for (Person *person in resultArray) { NSLog(@"personID =%d",person.personID); NSLog(@"personName=%@",person.personName); NSLog(@"personAge=%d",person.personAge); NSLog(@"personHeight=%lf",person.personHeight); NSLog(@"personLikes=%@",person.personLikes); }
-
<5>、把Person模型中表中字段
personName
改为name
-
在
Peson.h
修改personName
为name
/** 人的名字 */ // @property(nonatomic,strong) NSString *personName; // 改后的名字 @property(nonatomic,strong) NSString *name;
-
在
Peson.m
里面实现改表中名字的协议+(NSDictionary *)updateFieldNewNameReplaceOldName{ return @{@"name":@"personName"}; }
提示:字典的key是新字段名,value是旧的字段名
-
执行替换字段的方法
BOOL result = [JKSqliteModelTool updateTable:[Person class] uid:@"1"]; if(result){ NSLog(@"修改成功"); }else{ NSLog(@"修改失败"); }
-
-
<6>、删除Person模型(也可以说是删除这个Person模型的表)
Person *person = [[Person alloc]init]; BOOL result = [JKSqliteModelTool deleteModel:person uid:@"1"]; if(result){ NSLog(@"删除模型成功"); }else{ NSLog(@"删除模型失败"); }
-
最后,建议看着 demo 读这篇博客,里面有很多的知识可以去学习,这篇博客仅仅是引出 Realm 做铺垫,下篇博客我们再聊