iOS SQLite FMDB 事务.. 正确用法?

Posted

技术标签:

【中文标题】iOS SQLite FMDB 事务.. 正确用法?【英文标题】:iOS SQLite FMDB Transactions.. Correct usage? 【发布时间】:2011-09-28 15:28:49 【问题描述】:

我将尝试使用带有 FMDB SQLite ios 包装器的事务。

文档对交易有点模糊,但通过快速浏览一些功能,我得出了以下逻辑:

[fmdb beginTransaction];
    // Run the following query
    BOOL res1 = [fmdb executeUpdate:@"query1"];
    BOOL res2 = [fmdb executeUpdate:@"query2"];

if(!res1 || !res2) [fmdb rollback];
else [fmdb commit];

【问题讨论】:

【参考方案1】:

这似乎是一个有效的使用场景,我可能会在执行回滚之前添加输出 -lastErrorMessage-lastErrorCode 的值,以便您了解到底出了什么问题。

更好的是,在每个 -executeUpdate 之后进行这些调用,这样您就会知道每个语句之后是否发生错误:

[fmdb beginTransaction];

// Run the following query
BOOL res1 = [fmdb executeUpdate:@"query1"];
if (!res1) 
   NSLog(@"Error %d - %@", [fmdb lastErrorMessage], [fmdb lastErrorCode]);


BOOL res2 = [fmdb executeUpdate:@"query2"];
if (!res2) 
   NSLog(@"Error %d - %@", [fmdb lastErrorMessage], [fmdb lastErrorCode]);


if(!res1 || !res2) [fmdb rollback];
else [fmdb commit];

【讨论】:

【参考方案2】:

如果第一次失败,我不会尝试进行第二次更新。

bool ret = false;
[fmdb beginTransaction];
ret = [fmdb executeUpdate:@"query1"];
if (ret)

    ret = [fmdb executeUpdate:@"query2"];
    if (!ret)
    
         // report error 2
    


if(ret) 

    if (![fmdb commit])
    
        // panic!
    

else

    if (![fmdb rollback])
    
        // panic!
    

对于偏执的鲁棒性,你应该有一个 try ... catch 块,以防任何东西引发异常。如果你这样做,你可以利用它来发挥你的优势。

[fmdb beginTransaction];
@try

    if (![fmdb executeUpdate:@"query1"])
    
        // report error
        @throw someExcpetion;
    
    if (![fmdb executeUpdate:@"query2"])
    
        // report error
        @throw someExcpetion;
    
    [fmdb commit]

@catch(NSException* e)

    [fmdb rollback];
    // rethrow if not one of the two exceptions above

【讨论】:

【参考方案3】:

您还可以使用 FMDatabaseQueue 来处理您的事务,它是 fmdb 的一部分:

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) 
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];

    if (whoopsSomethingWrongHappened) 
        *rollback = YES;
        return;
    
    // etc…
    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
];

Documentation

【讨论】:

inTransaction 帮了大忙。谢谢老兄。 没有人提到whoopsSomethingWrongHappened 来自哪里... 这有一个缺点。您无法控制 beginTransaction 和 commit 方法。他们的返回值。如果 beginTransacion(在 inTransaction 中使用)返回 false 怎么办?你无法控制它【参考方案4】:

快捷方式:

let queue = FMDatabaseQueue(path: databaseURL.path!)

queue.inTransaction() 
    db, rollback in

    result = db.executeUpdate("INSERT INTO client VALUES (NULL, ?)", client.name ?? "")

    if result 
        client.ID = Int(db.lastInsertRowId())
     else 
        rollback.initialize(true)
        print("\(__FUNCTION__) insert into table failed: \(db.lastErrorMessage())")
    


queue.close()

【讨论】:

以上是关于iOS SQLite FMDB 事务.. 正确用法?的主要内容,如果未能解决你的问题,请参考以下文章

iOS-FMDB事务批量更新数据库

FMDB 如何让 sqlite 更简单 iOS?

iOS开发--SQLite重要框架FMDB的使用

iOS 上 Core Data 结合 FMDB

iOS sqlite/FMDB 更新不起作用

如何在 IOS Swift 中使用 SQLite 使用 FMDB 处理多个线程