总体内容
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 *)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
// 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 的类型,从而动