<h2>FMDB</h2>
<h3>1.簡(jiǎn)介</h3>
<p><code>FMDB</code>是iOS平臺(tái)的SQLite數(shù)據(jù)庫(kù)框架掏愁,它是以O(shè)C的方式封裝了SQLite的C語(yǔ)言API汪诉,它相對(duì)于cocoa自帶的C語(yǔ)言框架有如下的優(yōu)點(diǎn): </p>
<ul>
<li>使用起來(lái)更加面向?qū)ο螅∪チ撕芏嗦闊┳缪摇⑷哂嗟腃語(yǔ)言代碼 </li>
<li>對(duì)比蘋(píng)果自帶的Core Data框架叽掘,更加輕量級(jí)和靈活 </li>
<li>提供了多線程安全的數(shù)據(jù)庫(kù)操作方法,有效地防止數(shù)據(jù)混亂 </li>
</ul>
<p>注:<a target="_blank"><strong>FMDB的gitHub地址</strong></a> </p>
<h3>2.核心類</h3>
<p>FMDB有三個(gè)主要的類:</p>
<ul>
<li>
<p><strong>FMDatabase</strong>
一個(gè)FMDatabase對(duì)象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫(kù)侈百,用來(lái)執(zhí)行SQL語(yǔ)句</p>
</li>
<li>
<p><strong>FMResultSet</strong>
使用FMDatabase執(zhí)行查詢后的結(jié)果集 </p>
</li>
<li>
<p><strong>FMDatabaseQueue</strong>
用于在多線程中執(zhí)行多個(gè)查詢或更新,它是線程安全的 </p>
</li>
</ul>
<h3>3.打開(kāi)數(shù)據(jù)庫(kù)</h3>
<p>和c語(yǔ)言框架一樣翰铡,F(xiàn)MDB通過(guò)指定SQLite數(shù)據(jù)庫(kù)文件路徑來(lái)創(chuàng)建FMDatabase對(duì)象钝域,但FMDB更加容易理解,使用起來(lái)更容易锭魔,<strong>使用之前一樣需要導(dǎo)入<code>sqlite3.dylib</code></strong>例证。打開(kāi)數(shù)據(jù)庫(kù)方法如下: </p>
<pre><code class="objc">NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.db"];
FMDatabase *database = [FMDatabase databaseWithPath:path];
if (![database open]) {
NSLog(@"數(shù)據(jù)庫(kù)打開(kāi)失敗迷捧!");
}</code></pre>
<p>值得注意的是战虏,Path的值可以傳入以下三種情況: </p>
<ul>
<li>
<p>具體文件路徑,如果不存在會(huì)自動(dòng)創(chuàng)建</p>
</li>
<li>
<p>空字符串@""党涕,會(huì)在臨時(shí)目錄創(chuàng)建一個(gè)空的數(shù)據(jù)庫(kù),當(dāng)FMDatabase連接關(guān)閉時(shí)巡社,數(shù)據(jù)庫(kù)文件也被刪除</p>
</li>
<li>
<p>nil膛堤,會(huì)創(chuàng)建一個(gè)內(nèi)存中臨時(shí)數(shù)據(jù)庫(kù),當(dāng)FMDatabase連接關(guān)閉時(shí)晌该,數(shù)據(jù)庫(kù)會(huì)被銷毀 </p>
</li>
</ul>
<h3>4.更新</h3>
<p>在FMDB中肥荔,除查詢以外的所有操作,都稱為“更新”, 如:create朝群、drop燕耿、insert、update姜胖、delete等操作誉帅,使用<code>executeUpdate:</code>方法執(zhí)行更新: </p>
<pre><code class="objc">//常用方法有以下3種:
- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments
//示例
[database executeUpdate:@"CREATE TABLE IF NOT EXISTS t_person(id integer primary key autoincrement, name text, age integer)"];
//或者
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES(?, ?)", @"Bourne", [NSNumber numberWithInt:42]];</code></pre>
<h3>5.查詢</h3>
<p>查詢方法也有3種,使用起來(lái)相當(dāng)簡(jiǎn)單: </p>
<pre><code class="objc">- (FMResultSet )executeQuery:(NSString)sql, ...
- (FMResultSet )executeQueryWithFormat:(NSString)format, ...
- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments</code></pre>
<p>查詢示例: </p>
<pre><code class="objc">//1.執(zhí)行查詢
FMResultSet *result = [database executeQuery:@"SELECT * FROM t_person"];
//2.遍歷結(jié)果集
while ([result next]) {
NSString *name = [result stringForColumn:@"name"];
int age = [result intForColumn:@"age"];
}</code></pre>
<h3>6.線程安全</h3>
<p>在多個(gè)線程中同時(shí)使用一個(gè)FMDatabase實(shí)例是不明智的右莱。不要讓多個(gè)線程分享同一個(gè)FMDatabase實(shí)例蚜锨,它無(wú)法在多個(gè)線程中同時(shí)使用。 如果在多個(gè)線程中同時(shí)使用一個(gè)FMDatabase實(shí)例慢蜓,會(huì)造成數(shù)據(jù)混亂等問(wèn)題亚再。所以,請(qǐng)使用 FMDatabaseQueue晨抡,它是線程安全的氛悬。以下是使用方法:</p>
<ul>
<li>創(chuàng)建隊(duì)列则剃。</li>
</ul>
<pre><code class="objc">FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];</code></pre>
<ul>
<li>使用隊(duì)列</li>
</ul>
<pre><code class="objc">[queue inDatabase:^(FMDatabase *database) {
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_1", [NSNumber numberWithInt:1]];
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_2", [NSNumber numberWithInt:2]];
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_3", [NSNumber numberWithInt:3]];
FMResultSet *result = [database executeQuery:@"select * from t_person"];
while([result next]) {
}
}];</code></pre>
<p>而且可以輕松地把簡(jiǎn)單任務(wù)包裝到事務(wù)里: </p>
<pre><code class="objc">[queue inTransaction:^(FMDatabase *database, BOOL *rollback) {
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_1", [NSNumber numberWithInt:1]];
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_2", [NSNumber numberWithInt:2]];
[database executeUpdate:@"INSERT INTO t_person(name, age) VALUES (?, ?)", @"Bourne_3", [NSNumber numberWithInt:3]];
FMResultSet *result = [database executeQuery:@"select * from t_person"];
while([result next]) {
}
//回滾
*rollback = YES;
}];</code></pre>
<p> FMDatabaseQueue 后臺(tái)會(huì)建立系列化的G-C-D隊(duì)列,并執(zhí)行你傳給G-C-D隊(duì)列的塊如捅。這意味著 你從多線程同時(shí)調(diào)用調(diào)用方法棍现,GDC也會(huì)按它接收的塊的順序來(lái)執(zhí)行。</p>