FMDB
框架下载地址:https://github.com/ccgus/fmdb
速度比CoreData快几十倍,realm我一直没有用,不做过多评价,现在聊一聊我在项目中是如何使用FMDB的
单例封装###
创建一个WYSQLiteManager
继承自NSObject
,里面主要用到的是FMDB中的FMDatabaseQueue
#import <Foundation/Foundation.h>
#import "FMDB.h"
@class FMDatabaseQueue;
@interface WYSQLiteManager : NSObject
@property (nonatomic, strong) FMDatabaseQueue *queue;
+ (instancetype)sharedManager;
@end
.m中的代码:
#import "WYSQLiteManager.h"
// 数据库名称
NSString *const dbName = @"nightChat.db";
@implementation WYSQLiteManager
+ (instancetype)sharedManager {
static id _instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[WYSQLiteManager alloc] init];
});
return _instance;
}
- (instancetype)init {
if (self = [super init]) {
// 数据库在沙盒中的路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
path = [path stringByAppendingPathComponent:dbName];
// 使用数据库路径初始化FMDatabaseQueue
self.queue = [[FMDatabaseQueue alloc] initWithPath:path];
[self createTables];
}
return self;
}
- (void)createTables {
NSString *path = [[NSBundle mainBundle] pathForResource:@"tables.sql" ofType:nil];
NSError *error = nil;
// 加载所有的建表语句
NSString *sql = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
if (error) {
NSLog(@"加载数据库建表语句错误--%@", error);
}
// 创建表
[self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeStatements:sql];
}];
}
我的tables.sql[这里只给出了一个建表语句]
-- fateMessage 有缘人消息列表
CREATE TABLE IF NOT EXISTS "T_Fate_Message" (
"messageId" INTEGER NOT NULL, -- 消息ID
"content" TEXT, -- 消息内容
"owner_id" INTEGER, -- 消息拥有者ID
"sender_id" INTEGER, -- 消息发送者ID
"receiver_id" INTEGER, -- 消息接受者ID
"timestamp" LONG, -- 消息发送时间
"deliveryState" INTEGER, -- 消息发送状态
"mfrom" TEXT, -- 消息来源的环信用户名
"mto" TEXT, -- 消息接受者的环信用户名
"extern" TEXT, -- 预留字段
"ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
);
啰嗦两句,一般创建表的时候都会有一两个预留字段,因为如果使用了sqlite过后,项目发版上线了,后面要对数据库表做变动[例如增加字段],这个时候是需要做数据迁移的,这个会比较麻烦,所以一般的办法都是在建表的时候就多创建两个预留字段.并且在大多数时候存储的都是json字符串,这样的变动性会比较好,一般单独的字段大多是需要用作查询处理的.
数据库操作##
一般我们还会单独针对不同模块的本地化数据操作创建不同的数据访问层,例如这里创建一个WYFateMessageDAL
/// 有缘人消息保存
///
/// @param message 要保存的消息
+ (BOOL)fateMessageSave:(EMMessage *)message {
NSString *sql = @"insert or replace into T_Fate_Message (messageId, content, owner_id, timestamp, deliveryState, mfrom, mto) values (?, ?, ?, ?, ?, ?, ?);";
return [self insertFateMessage:message sql:sql];
}
/// 保存有缘人消息
///
/// @param message 有缘人消息
/// @param sql sql语句
///
/// @return 插入结果
+ (BOOL)insertFateMessage:(EMMessage *)message sql:(NSString *)sql {
__block BOOL success = false;
[[WYSQLiteManager sharedManager].queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
success = [db executeUpdate:sql, message.messageId, message.contentText, GetUserID, @(message.timestamp), @(message.deliveryState), message.from, message.to];
[self stateLog:success rollback:rollback];
}];
return success;
}
注意点###
FMDatabaseQueue
是一个串行队列,目的就是为了保证数据的安全性,所以我们在做数据操作的时候一定要注意多线程并发访问的数据造成的数据错乱,所以在使用的时候记住在主线程做数据库访问操作.
网友评论