FMDB
框架下載地址:https://github.com/ccgus/fmdb
速度比CoreData快幾十倍,realm我一直沒有用,不做過多評價(jià),現(xiàn)在聊一聊我在項(xiàng)目中是如何使用FMDB的
單例封裝###
創(chuàng)建一個(gè)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"
// 數(shù)據(jù)庫名稱
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]) {
// 數(shù)據(jù)庫在沙盒中的路徑
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
path = [path stringByAppendingPathComponent:dbName];
// 使用數(shù)據(jù)庫路徑初始化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(@"加載數(shù)據(jù)庫建表語句錯(cuò)誤--%@", error);
}
// 創(chuàng)建表
[self.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[db executeStatements:sql];
}];
}
我的tables.sql[這里只給出了一個(gè)建表語句]
-- fateMessage 有緣人消息列表
CREATE TABLE IF NOT EXISTS "T_Fate_Message" (
"messageId" INTEGER NOT NULL, -- 消息ID
"content" TEXT, -- 消息內(nèi)容
"owner_id" INTEGER, -- 消息擁有者ID
"sender_id" INTEGER, -- 消息發(fā)送者ID
"receiver_id" INTEGER, -- 消息接受者ID
"timestamp" LONG, -- 消息發(fā)送時(shí)間
"deliveryState" INTEGER, -- 消息發(fā)送狀態(tài)
"mfrom" TEXT, -- 消息來源的環(huán)信用戶名
"mto" TEXT, -- 消息接受者的環(huán)信用戶名
"extern" TEXT, -- 預(yù)留字段
"ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT
);
啰嗦兩句,一般創(chuàng)建表的時(shí)候都會(huì)有一兩個(gè)預(yù)留字段,因?yàn)槿绻褂昧藄qlite過后,項(xiàng)目發(fā)版上線了,后面要對數(shù)據(jù)庫表做變動(dòng)[例如增加字段],這個(gè)時(shí)候是需要做數(shù)據(jù)遷移的,這個(gè)會(huì)比較麻煩,所以一般的辦法都是在建表的時(shí)候就多創(chuàng)建兩個(gè)預(yù)留字段.并且在大多數(shù)時(shí)候存儲(chǔ)的都是json字符串,這樣的變動(dòng)性會(huì)比較好,一般單獨(dú)的字段大多是需要用作查詢處理的.
數(shù)據(jù)庫操作##
一般我們還會(huì)單獨(dú)針對不同模塊的本地化數(shù)據(jù)操作創(chuàng)建不同的數(shù)據(jù)訪問層,例如這里創(chuàng)建一個(gè)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 插入結(jié)果
+ (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;
}
注意點(diǎn)###
FMDatabaseQueue是一個(gè)串行隊(duì)列,目的就是為了保證數(shù)據(jù)的安全性,所以我們在做數(shù)據(jù)操作的時(shí)候一定要注意多線程并發(fā)訪問的數(shù)據(jù)造成的數(shù)據(jù)錯(cuò)亂,所以在使用的時(shí)候記住在主線程做數(shù)據(jù)庫訪問操作.