zoukankan      html  css  js  c++  java
  • FMDB简单使用

    概念

    FMDB 是 iOS 平台的 SQLite 数据库框架; FMDB 以 OC 的方式封装了 SQLite 的 C 语言 API。以面相对象的方式操作数据库。
     

    FMDB的优点

    1) 使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码;
    2) 对比苹果自带的 Core Data 框架,更加轻量级和灵活;
    3) 提供了多线程安全的数据库操作方法,有效地防止数据混乱;
     

    API讲解:

    FMDB的三个主要类别:

    • FMDatabase ——代表一个 SQLite 数据库。 用于执行 SQL 语句。
    • FMResultSet ——执行查询一个 FMDatabase 的结果集
    • FMDatabaseQueue ——在多线程操作更新和查询时,需要使用这个类,它是线程安全的。

     

    非线程安全数据库创建方法:

    /**
     *  @brief 创建一个数据库对象
         数据库被创建时,数据库文件路径有三种情况:
         1)具体文件路径 : 如果不存在会自动创建;
         2)空字符串@"" : 会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除;
         3)nil : 会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁;
     *
     *  @param inPath 数据库路径(绝对路径)
     *
     *  @return 返回对象结果
     */
    + (instancetype)databaseWithPath:(NSString*)inPath;
    /**
     *  @brief 打开数据库
     *
     *  @return YES,成功;NO,失败
     */
    - (BOOL)open;
    /**
     *  @brief FMDB 中该方法相当于 `CREATE`,`UPDATE`,`INSERT`,`DELETE`(增删改)
     *
     *  @param sql 指定执行的 SQL 语句
     *
     *  @return YES,执行成功;NO,失败
     */
    - (BOOL)executeUpdate:(NSString*)sql, ...;

    线程安全数据库创建:

    /**
     *  @brief 创建数据库实例(查看源码可知:调用该方法后,数据库已打开)
     *
     *  @param aPath 数据库绝对路径
     *
     *  @return 返回数据对线程对象
     */
    + (instancetype)databaseQueueWithPath:(NSString*)aPath;
    
    /**
     *  @brief 同步队列执行数据库操作(dispatch_sync实现,该方法线程安全)
     *
     *  @param block 回调数据库本身,我们可以在代码块内操作数据库
     */
    - (void)inDatabase:(void (^)(FMDatabase *db))block;

    代码

    非线程安全代码:

    ///=============================================================================
    /// @name 非线程安全数据库
    ///=============================================================================
    #pragma mark - 创建非线程安全的数据库
    - (void)createNonatomicDBWithDbPath:(NSString *)dbPath {
        // 创建数据库的实例
        self.db = [FMDatabase databaseWithPath:dbPath];
        
        // 打开数据库
        BOOL flag = [self.db open];
        if (flag) {
            DLog(@"db open success.");
        } else {
            DLog(@"db open failed.");
        }
        
        // 创建表
        BOOL exeFlag = [self.db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_kingdev (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, phone TEXT NOT NULL, height REAL NOT NULL)"];
        if (exeFlag) {
            DLog(@"CREATE success");
        } else {
            DLog(@"CREATE failed");
        }
    }
    
    //
    - (IBAction)insertInto:(id)sender {
        BOOL flag = [self.db executeUpdate:@"INSERT INTO t_kingdev (name, phone, height) VALUES (?, ?, ?)", [NSString stringWithFormat:@"张%d", arc4random_uniform(50)], [NSString stringWithFormat:@"%d", arc4random_uniform(20)], [NSNumber numberWithFloat:(arc4random_uniform(1000) / 10.f)]];
        if (flag) {
            DLog(@"INSERT INTO success");
        } else {
            DLog(@"INSERT INTO failed");
        }
    }
    
    //
    - (IBAction)delete:(id)sender {
        // 删除  id 大于 20 的数据库数据
        BOOL flag = [self.db executeUpdate:@"DELETE FROM t_kingdev WHERE id > 20"];
        if (flag) {
            DLog(@"DELETE success");
        } else {
            DLog(@"DELETE failed");
        }
    }
    
    //
    - (IBAction)update:(id)sender {
        // '张三' ——> 改为 'Flora'
        [self.db executeQuery:@"update t_kingdev set name = 'Flora' where name = '张三';"];
    }
    
    //
    - (IBAction)select:(id)sender {
        FMResultSet *resultSet = [self.db executeQuery:@"select * from t_kingdev"];
        // 从结果集往下找
        while ([resultSet next]) {
            // 根据字段取值
            NSString *name = [resultSet stringForColumn:@"name"];
            NSString *phone = [resultSet stringForColumn:@"phone"];
            double height = [resultSet doubleForColumn:@"height"];
            DLog(@"name=%@ phone=%@ height=%f", name, phone, height);
        }
    }
    线程安全数据库和事务代码:
    ///=============================================================================
    /// @name 数据库多线程安全和事务
    ///=============================================================================
    /** 
     模拟场景:
     甲:500元
     乙:1000元
     乙给甲转账500元。
     */
    #pragma mark - 创建线程安全的数据库
    - (void)createAtomicDB {
        NSString *docDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
        NSString *dbPath = [docDir stringByAppendingPathComponent:@"t_bank.sqlite"];
        // 创建队列且默认开发了数据库
        FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
        [queue inDatabase:^(FMDatabase *db) {
            // code····Operate db
            BOOL flag = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_bank (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, money INTEGER NOT NULL)"];
            if (flag) {
                DLog(@"create t_bank success");
            } else {
                DLog(@"create t_bank failed");
            }
        }];
        _queue = queue;
    }
    
    //
    - (IBAction)at_Add:(id)sender {
        [_queue inDatabase:^(FMDatabase *db) {
            BOOL flag = [db executeUpdate:@"INSERT INTO t_bank (name, money) VALUES (?, ?);", @"", @500];
            [db executeUpdate:@"INSERT INTO t_bank (name, money) VALUES (?, ?);", @"", @1000];
            if (flag) {
                DLog(@"INSERT INTO t_bank success");
            } else {
                DLog(@"INSERT INTO t_bank failed");
            }
        }];
    }
    
    //
    - (IBAction)at_delete:(id)sender {
        [_queue inDatabase:^(FMDatabase *db) {
            BOOL flag = [db executeUpdate:@"DELETE FROM t_bank"];
            if (flag) {
                DLog(@"DELETE t_bank success");
            } else {
                DLog(@"DELETE t_bank failed");
            }
        }];
    }
    
    /** 
     
     操作1:乙 (1000 - 500) 扣500
     操作2:甲 (500 + 500)  得500
     
     操作1和操作2必须一起成功,称为一个不可分割的工作单元。所以我们用到了事务
     
     若事务内的操作失败了某个,则数据库回滚到事务之前的状态!!
     
     */
    //
    - (IBAction)at_update:(id)sender {
        [_queue inDatabase:^(FMDatabase *db) {
            
            // 开启事务
            [db beginTransaction];
            
            // 操作1
            BOOL flag1 = [db executeUpdate:@"UPDATE t_bank SET money = 500 WHERE name = '乙';"];
            if (flag1) {
                DLog(@"flag1UPDATE t_bank success");
            } else {
                DLog(@"flag1UPDATE t_bank failed");
                
                // 失败回滚
                [db rollback];
            }
            
            // 操作2
            BOOL flag2 = [db executeUpdate:@"UPDATE t_bank SET money = 1000 WHERE name = '甲';"];
            if (flag2) {
                DLog(@"flag2UPDATE t_bank success");
            } else {
                DLog(@"flag2UPDATE t_bank failed");
                
                // 失败回滚
                [db rollback];
            }
            
            // 提交事务
            [db commit];
        }];
    }
    
    //
    - (IBAction)at_slect:(id)sender {
        [_queue inDatabase:^(FMDatabase *db) {
            FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_bank"];
            while ([rs next]) {
                DLog(@"name = %@  money = %d", [rs stringForColumn:@"name"], [rs intForColumn:@"money"]);
            }
        }];
    }
    参考:
     
    尊重作者劳动成果,转载请注明: 【kingdev】
  • 相关阅读:
    Allegro PCB Design GXL (legacy) 使用slide无法将走线推挤到焊盘的原因
    OrCAD Capture CIS 16.6 导出BOM
    Altium Designer (17.0) 打印输出指定的层
    Allegro PCB Design GXL (legacy) 将指定的层导出为DXF
    Allegro PCB Design GXL (legacy) 设置十字大光标
    Allegro PCB Design GXL (legacy) 手动更改元器件引脚的网络
    magento产品导入时需要注意的事项
    magento url rewrite
    验证台湾同胞身份证信息
    IE8对css文件的限制
  • 原文地址:https://www.cnblogs.com/xiu619544553/p/5364586.html
Copyright © 2011-2022 走看看