靜以修身,儉以養德html
原文連接git
SQLite
數據庫,也能夠是XML文件、甚至是內存; 比較流行的第三方框架FMDB是對SQLite操做的封裝Realm:適用於iOS (一樣適用於Swift&Objective-C)和Android的跨平臺移動數據庫,是NoSQL框架,官方定位是取代SQLite。具體可參考Realm(Java)那些事github
Realm很是的特點是數據變動通知,查詢,存儲性能比SQLite好,可是體積大、存入Realm的對象必須繼承RealmObject,侵入性強,Realm中存儲對象不允跨線程訪問sql
非關係型數據庫還有LevelDB、RocksDB數據庫
說明:線程模式能夠在編譯時(經過源碼編譯SQLite庫時)、啓動時(使用SQLite的應用程序初始化時)或者運行時(建立數據庫鏈接時)來指定。通常而言,運行時指定的模式將覆蓋啓動時的指定模式,啓動時指定的模式將覆蓋編譯時指定的模式。可是,單線程模式一旦被指定,將沒法被覆蓋。默認的線程模式是串行模式。api
//0:單線程模式;
//1:串行模式;
//2:多線程模式
複製代碼
//FMDB 中代碼
+ (BOOL)isSQLiteThreadSafe {
// make sure to read the SQLite headers on this guy!
return SQLite3_threadsafe() != 0;
}
複製代碼
假如在編譯時沒有指定單線程模式,就能夠在應用程序初始化時使用SQLite3_config()函數修改線程模式。緩存
SQLite_CONFIG_SINGLETHREAD //單線程模式
SQLite_CONFIG_MULTITHREAD //多線程模式
SQLite_CONFIG_SERIALIZED //串行模式
複製代碼
SQLite_OPEN_NOMUTEX //建立多線程模式的鏈接(沒有指定單線程模式的狀況下)
SQLite_OPEN_FULLMUTEX //建立串行模式的鏈接
複製代碼
要保證數據庫使用安全,通常能夠採用以下幾種模式安全
SQLite
採用單線程模型,用專門的線程(同時只能有一個任務執行訪問) 進行訪問SQLite
採用多線程模型,每一個線程都使用各自的數據庫鏈接 (即 SQLite3 *
)SQLite
採用串行模型,全部線程都公用同一個數據庫鏈接。 寫操做的併發性並很差,當多線程進行訪問時實際上仍舊須要互相等待,而讀操做所須要的 SHARED
鎖是能夠共享的,因此爲了保證最高的併發性,推薦bash
WAL
模式SQLite3_prepare
編譯結果BEGIN
和 COMMIT
作顯示事務,減小屢次的自動事務消耗//打開數據庫鏈接 定義
SQLite_API int SQLite3_open(
const char *filename, /* Database filename (UTF-8) */
SQLite3 **ppDb /* OUT: SQLite db handle */
);
//使用數據庫鏈接
//db是SQLite3對象,SQLite3 *db = nil;
SQLite3_open([sqlPath UTF8String], &db);
//打開
int SQLite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
SQLite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
const char *zVfs /* Name of VFS module to use */
);
複製代碼
參數1:數據庫的路徑(由於須要的是C語言的字符串,而不是NSString因此必須進行轉換)微信
參數2:SQLite的數據庫的操做句柄(指向指針的指針)
//執行sql語句 定義
SQLite_API int SQLite3_exec(
SQLite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
//使用
int result = SQLite3_exec(db, sql.UTF8String, nil, nil, nil);
if (result == SQLite_OK) {
//exec ok
} else {
//exec failed
}
複製代碼
//將sql文本轉換成一個準備語句(prepared statement)對象,同時返回這個對象的指針,它實際上並不執行(evaluate)這個SQL語句,它僅僅爲執行準備這個sql語句。
SQLite_API int SQLite3_prepare_v2(
SQLite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
SQLite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
//使用
result = SQLite3_prepare_v2(_db, [sql UTF8String], -1, &pStmt, 0);
if (result == SQLite_OK) {
//exec ok
} else {
//exec failed
}
複製代碼
//關閉數據庫 定義
SQLite_API int SQLite3_close(SQLite3*);
//使用
SQLite3_close(db);
複製代碼
說明:具體API參考C-language Interface Specification for SQLite,FMDB中對SQLite3的操做作了很好的封裝,具體可參考FMDB的FMDatabase文件
參考 SQLite線程模式探討
FMDB是iOS平臺的SQLite數據庫框架,iOS項目中使用十分普遍。
說明:在FMDB中,SQLite運行在多線程模式,一個數據庫鏈接在同一個時間只能在一個線程操做 ,應該是在編譯時候肯定的,固然也能夠在打開數據庫鏈接時候,指定線程模式是 多線程或串行。
FMDatabase
經過一個 SQLite 數據庫文件路徑建立的,此路徑能夠是:
一個文件的系統路徑。磁盤中能夠不存在此文件,由於若是不存在會自動爲你建立。
一個空的字符串 `@""`。會在臨時位置建立一個空的數據庫,當 `FMDatabase` 鏈接關閉時,該數據庫會被刪除。
NULL`。會在內存中建立一個數據庫,當 `FMDatabase` 鏈接關閉時,該數據庫會被銷燬。
複製代碼
FMDatabase
必須執行open,在這裏才能正在建立並打開SQLite3對象。
FMDatabase *db = [FMDatabase databaseWithPath:dbpath];
[db open];
//...
//關閉
[db close];
複製代碼
//數據庫查詢
FMResultSet *rs = [db executeQuery:@"select * from people"];
//利用next函數
while ([rs next]) {
NSLog(@"%@ %@",[rs stringForColumn:@"name"],[rs stringForColumn:@"age"]);
}
複製代碼
FMResultSet
經過調用 -executeQuery...
方法之一執行 SELECT
語句返回數據庫查詢結果FMResultSet
對象,而後就能夠遍歷查詢結果了。SQL 語句中除過 SELECT
語句均可以稱之爲更新操做。包括 CREATE
,UPDATE
,INSERT
,ALTER
,COMMIT
,BEGIN
,DETACH
,DROP
,END
,EXPLAIN
,VACUUM
,REPLACE
等。
執行更新語句後會返回一個 BOOL
值,返回 YES
表示執行更新語句成功,返回 NO
表示出現錯誤,能夠經過調用 -lastErrorMessage
和 -lastErrorCode
方法獲取更多錯誤信息。
//建立表
[db executeUpdate:@"CREATE TABLE IF NOT EXISTS people (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER DEFAULT 1)"];
//插入操做
[db executeUpdate:@"INSERT INTO people(name,age) VALUES (?,?)", @"LiLei",[NSNumber numberWithInteger:28]]
複製代碼
FMDatabaseQueue *databaseQueue = [FMDatabaseQueue databaseQueueWithPath:dbpath];
[databaseQueue inDatabase:^(FMDatabase *db) {
//
[db executeUpdate:@"CREATE TABLE IF NOT EXISTS people (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER DEFAULT 1)"];
}];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[databaseQueue inDatabase:^(FMDatabase *db) {
BOOL isSuccess = [db executeUpdate:@"INSERT INTO people(name,age) VALUES (?,?)", @"LiLei",[NSNumber numberWithInteger:28]];
if (isSuccess) {
NSLog(@"插入成功1");
}
}];
});
dispatch_async(queue, ^{
[databaseQueue inDatabase:^(FMDatabase *db) {
BOOL isSuccess = [db executeUpdate:@"INSERT INTO people(name,age) VALUES (?,?)", @"LiLei",[NSNumber numberWithInteger:28]];
if (isSuccess) {
NSLog(@"插入成功2");
}
}];
});
複製代碼
基於FMDB實現的ORM框架