一、主要思想
将整个数据模型 model
作为数据库表中的一个键值来存储(在创建表的SQLite
语句中model
的字段类型为 BLOB
,这样省去了根据model
的属性一一对应创建数据库字段)
二、FMDB 简介
简介:
FMDB
是iOS
平台的SQLite
数据库框架,FMDB
以OC
的方式封装了SQLite
的C
语言API
优点:
使用起来更加面向对象,省去了很多麻烦、冗余的C
语言代码;对比苹果自带的Core Data
框架,更加轻量级和灵活;提供了多线程安全的数据库操作方法,有效地防止数据混乱
核心类:
FMDatabase:
一个 FMDatabase
对象就代表一个单独的SQLite
数据库,用来执行SQL
语句
FMResultSet:
使用FMDatabase
查询之后的结果集
FMDatabaseQueue:
用于在多线程中执行多个查询或更新,它是线程安全的
三、具体步骤
(一)准备
创建Xcode
测试项目,将FMDB导入项目
(二)FMDB
封装增删改查
(1)创建工具类, 引入FMDB
头文件 #import <FMDB/FMDB.h>
(2)创建 NSObject
的分类,添加@property (nonatomic, assign) UInt32 user_id;
属性,使用runtime
添加set
和get
方法
@interface NSObject (Extra)
@property (nonatomic, assign) UInt32 user_id;
@end
@implementation NSObject (Extra)
static NSString *User_Id_Key = @"userIdKey";
- (void)setUser_id:(UInt32)user_id {
objc_setAssociatedObject(self, &User_Id_Key, @(user_id), OBJC_ASSOCIATION_ASSIGN);
}
- (UInt32)user_id {
NSNumber *num = objc_getAssociatedObject(self, &User_Id_Key);
return num.intValue;
}
@end
这里的user_id
用来作为model
的id
,用来当做表数据中的主键,后面会通过这个id
来进行数据库的删除和修改操作。由于user_id
使用了UInt32
类型,但是runtime
不可以直接添加基本数据类型的属性(会报错),所以这里我就转换成了对象
(3)封装增删改查方法
创建全局静态的FMDatabase
成员变量来进行数据库操作
NSString
类型的tableName
用来存储表的名称(当创建多个表的时候,我的这种方法可能会出问题--->未验证)
@interface DNFMDBTool ()
// 用来存储数据库表的名称
@property (nonatomic, copy) NSString *tableName;
@end
static FMDatabase * _db;
创建打开数据库
获取沙盒路径创建、打开数据库
- (FMDatabase *)dn_openDatabase {
NSString * path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
NSString * dbPath = [path stringByAppendingPathComponent:@"DNFMDBTools.sqlite"];
_db = [FMDatabase databaseWithPath:dbPath];
if ([_db open]) {
DNLog(@"open dataBase sueccess");
}
return _db;
}
创建表
(这里将表的名字存储为全局的变量,在创建多张表是可能会出问题)
/** 创建表 */
- (void)dn_createTable:(NSString *)tableName {
self.tableName = tableName;
[self dn_openDatabase];
NSString *sql = [NSString stringWithFormat:@"create table if not exists %@(id integer primary key autoincrement, model BLOB)", self.tableName];
BOOL result = [_db executeUpdate:sql];
if (result) {
DNLog(@"create table success");
}
}
插入数据
这里将传入的将要存储的model
归档为 NSData
类型,对应存储为数据库表中的 BLOB
类型
- (void)dn_insertData:(id)data {
[self dn_openDatabase];
NSData *modelData = [NSKeyedArchiver archivedDataWithRootObject:data];
NSString *sql = [NSString stringWithFormat:@"insert into %@(model) values (?)", self.tableName];
BOOL result = [_db executeUpdate:sql values:@[modelData] error:nil];
if (result) {
DNLog(@"insert data success");
}
[_db close];
}
删除数据
这里将刚才我们在分类中添加的 user_id
作为我们删除数据的标识
- (void)dn_deleteDateUid:(UInt32)uid {
[self dn_openDatabase];
NSString *sql = [NSString stringWithFormat:@"delete from %@ where id = ?", self.tableName];
BOOL result = [_db executeUpdate:sql values:@[@(uid)] error:nil];
if (result) {
DNLog(@"delete data success");
}
[_db close];
}
更新数据
这里将传入进来的model
归档为data
类型,分类中添加的 user_id
作为我们更新数据的标识
- (void)dn_updateData:(id)data uid:(UInt32)uid {
[self dn_openDatabase];
NSData *modelData = [NSKeyedArchiver archivedDataWithRootObject:data];
NSString * sql = [NSString stringWithFormat:@"update %@ set model = ? where id = ?", self.tableName];
BOOL result = [_db executeUpdate:sql values:@[modelData, @(uid)] error:nil];
if (result) {
DNLog(@"update data success");
} else {
[_db rollback];
}
[_db close];
}
查询数据
利用 FMResultSet
查询数据库得到的结果集,对应获取数据库中的主键id
和存储的数据类型model
,并将 NSData
类型的modelData
反归档,并将对应的model
模型放到数组中返回
- (NSMutableArray *)dn_selectAllData {
[self dn_openDatabase];
NSString *sql = [NSString stringWithFormat:@"select * from %@", self.tableName];
FMResultSet *result = [_db executeQuery:sql];
NSMutableArray *resultArr = [NSMutableArray array];
while (result.next) {
NSObject *model = [[NSObject alloc] init];
// 获取表中存储字段对应的值
NSData *modelData = [result dataForColumn:@"model"];
UInt32 uid = [result intForColumn:@"id"];
model = [NSKeyedUnarchiver unarchiveTopLevelObjectWithData:modelData error:nil];
model.user_id = uid;
[resultArr addObject:model];
}
[_db close];
return resultArr;
}
删除表
- (void)dropTable {
[self dn_openDatabase];
NSString *sql = [NSString stringWithFormat:@"drop table if exists %@", self.tableName];
BOOL result = [_db executeUpdate:sql withArgumentsInArray:@[]];
if (result) {
NSLog(@"drop table success");
}
[_db close];
}
以上就是我关于FMDB
封装的全部内容,欢迎各位大佬指正错误。Demo地址