美文网首页
FMDB使用

FMDB使用

作者: coder_hong | 来源:发表于2016-09-12 17:45 被阅读258次

框架地址:[https://github.com/ccgus/fmdb]

  • 下载框架


    Snip20160912_6.png
  • 首先要明白框架中几个重要的类

    • FMDatabase 代表一个数据库 并且可以使用它执行sqlite语句
    • FMDatabaseQueue 是线程安全的存储跟读取数据 这里有一个概念---事物
    • FMResultSet 结果集 从数据库中读取数据的集合
  • 使用之前会发现编译报错,需要先在Build Phases->Link Binary With Libraries->导入libsqlite3.tbd 再次编译就👌

FMDatabase

  • 首先我们我们不考虑线程安全下使用FMDatabase来创建数据库实现离线缓存
    • 导入#import "FMDB.h"
// 1.获得数据库路径
     NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    // 2.创建数据对象
    FMDatabase *dataBase = [FMDatabase databaseWithPath:path];
    
    // 3.打开数据库的时候首先判断当前数据库是否存在, 如果不存储在就创建一个并打开, 如果存储在那么就不创建直接打开
    BOOL isSuccess = [dataBase open];
    if (!isSuccess) {
        NSLog(@"打开数据库失败");
    }else{
        NSLog(@"打开数据库成功");
    
    }
}
  • 创建好数据库之后,接下来就是根据我们的需求在数据库中中创建表了,一个数据库可以创建多张表, 一张表包含多个字段,也就是对应表的column, 表是有row跟column构成, 有点类似Excle表

  • 细节不多说 创建一个完整的字段表

// 数据库前提是open状态
    /**
     * PRIMARY KEY 主键
     * AUTOINCREMENT 自动增量
     * UNIQUE 唯一
     * DEFAULT 默认值
     *  @param INTEGER 整型
     *  @param TEXT    文本
     *  @param REAL    浮点型
     *  @param
     *  @param BLOB    二进制
     */
    BOOL isSuccess = [dataBase executeUpdate:@"CREATE TABLE IF NOT EXIST t_table (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, age INTEGER  NOT NULL UNIQUE DEFAULT 0, score REAL NOT NULL unique, data BLOB);"];
    
    if (!isSuccess) {
        NSLog(@"创建表成功");
    }else{
        NSLog(@"创建表失败");
        
    }
  • 表创建完成了,接下来就是我们利用FMDatabase对象要插入数据了, 这里我们了解一下插入数据的常见3中写法
    /**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型*/
    [dataBase executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
    /**此种方式后面拼接的参数可以为int double等基本数据类型 因为是使用的占位符*/
    [dataBase executeUpdateWithFormat:@"insert into t_table(name, age, score, data) values(%@, %d , %f, %@)", @"jake", 12, 91.0, [NSData data]];
    /**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型 将对象依次防近视数组*/
    [dataBase executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)" withArgumentsInArray:@[@12, @91.0, [NSData data]]];

-注意 当我们存储表中BLOB 对应的字段如果为字典的时候,这个时候我们不应该把字典往里存,应当使用[NSKeyedArchiver archivedDataWithRootObject:<#(nonnull id)#>] 将字典转换成NSData类型, 这样当我们取出数据的时候取出的是NSData类型,再将NSData类型数据通过[NSKeyedUnarchiver unarchiveObjectWithData:<#(nonnull NSData *)#>];反归档得到就是字典,如果直接存字典,从数据数据库中取出的是字符串, 字典装模型时候会报错

  • 下面再说一下查表, 更行表 删除表数据就不说了,跟插入数据一样 自己研究
  • 书写格式几乎相同 就是返回结果是FMResultSet类型(结果集), 这时候根据遍历结果集取出每一条数据
    /**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型*/
    [dataBase executeQuery:@"select *From t_table;"];
    /**此种方式后面拼接的参数可以为int double等基本数据类型 因为是使用的占位符*/
    [dataBase executeQueryWithFormat:@"SELECT name, age, score from t_table where name = %@", @"jake"];
    /**此种方式后面拼接的参数必须为对象 不可以为int double等基本数据类型 将对象依次防近视数组*/
    [dataBase executeQuery:@"select *from t_table where age > ?" withArgumentsInArray:@[@12]];
  • 拿查整个表的全部数据为例
 FMResultSet * resultSet = [dataBase executeQuery:@"select *From t_table;"];
    while ([resultSet next]) {
        // 通过字段获取 文本数据
        [resultSet stringForColumn:@"name"];
        // 也可以通过Column来获取
        [resultSet stringForColumnIndex:2];
        
        // 通过字段获取 对象数据
        [resultSet objectForColumnName:@"dict"];
        
    }
  • 关于FMResultSet使用结合如下
/* 获取下一个记录 */
       - (BOOL)next;
       /* 获取记录有多少列 */
       - (int)columnCount;
       /* 通过列名得到列序号,通过列序号得到列名 */
       - (int)columnIndexForName:(NSString *)columnName;
       - (NSString *)columnNameForIndex:(int)columnIdx;
       /* 获取存储的整形值 */
       - (int)intForColumn:(NSString *)columnName;
       - (int)intForColumnIndex:(int)columnIdx;
       /* 获取存储的长整形值 */
       - (long)longForColumn:(NSString *)columnName;
       - (long)longForColumnIndex:(int)columnIdx;
       /* 获取存储的布尔值 */
       - (BOOL)boolForColumn:(NSString *)columnName;
       - (BOOL)boolForColumnIndex:(int)columnIdx;
       /* 获取存储的浮点值 */
       - (double)doubleForColumn:(NSString *)columnName;
       - (double)doubleForColumnIndex:(int)columnIdx;
       /* 获取存储的字符串 */
       - (NSString *)stringForColumn:(NSString *)columnName;
       - (NSString *)stringForColumnIndex:(int)columnIdx;
       /* 获取存储的日期数据 */
       - (NSDate *)dateForColumn:(NSString *)columnName;
       - (NSDate *)dateForColumnIndex:(int)columnIdx;
       /* 获取存储的二进制数据 */
       - (NSData *)dataForColumn:(NSString *)columnName;
       - (NSData *)dataForColumnIndex:(int)columnIdx;
       /* 获取存储的UTF8格式的C语言字符串 */
       - (const unsigned cahr *)UTF8StringForColumnName:(NSString *)columnName;
       - (const unsigned cahr *)UTF8StringForColumnIndex:(int)columnIdx;
       /* 获取存储的对象,只能是NSNumber、NSString、NSData、NSNull */
       - (id)objectForColumnName:(NSString *)columnName;
       - (id)objectForColumnIndex:(int)columnIdx;

FMDatabaseQueue

  • 如果项目中开启多个线程同时访问一个数据库的时候,需要考虑到线程安全的问题了,那么就要使用这个类来对数据库操作了, 那么我们还要理解一个概念 事物 常说开启事物 提交事物 回滚事物 是什么意思呢? 为什么需要开启事物呢

  • 说个情形就明白了,加入我们像一个数据库表中插入一百条数据, 我们可能会执行一百条SQLite语句,如果当我们执行到一半的时候出错了,那么我们需要回滚, 让之前执行的的数据恢复之前数据,也就是一句话,我们需要所有的语句都执行成功才生效,那么我们就需要开启事物,当确定所有的语句都执行成功就提交事物, 如果中途出错,那么就回滚事物

  • 首先我们不开启事物,就线程安全来使用FMDB

// 1.获得数据库路径
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    
    // 创建FMDatabaseQueue 同时会创建数据库 如果数据库不存在
    FMDatabaseQueue *baseQueue = [FMDatabaseQueue databaseQueueWithPath:path];
  • 当我们对数据库进行CRUDde的时候调用- (void)inDatabase:(void (^)(FMDatabase *db))block, 在block回调给我的FMDatabase对象进行操作 ,操作跟上面一样的 例如
[baseQueue inDatabase:^(FMDatabase *db) {
        // 打开数据库 创建表
        BOOL isSuccess = [db open];
        if (!isSuccess) {
            NSLog(@"打开数据库失败");
        }else{
            NSLog(@"打开数据库成功");
            
            // 插入数据
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        }
        
    }];
  • 使用一下开启事物, 加入我们插入同时插入十条数据
// 1.获得数据库路径
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"daba.sqlist"];
    
    // 创建FMDatabaseQueue 同时会创建数据库 如果数据库不存在
    FMDatabaseQueue *baseQueue = [FMDatabaseQueue databaseQueueWithPath:path];
    
    [baseQueue inDatabase:^(FMDatabase *db) {
        // 打开数据库 创建表
        BOOL isSuccess = [db open];
        if (!isSuccess) {
            NSLog(@"打开数据库失败");
        }else{
            NSLog(@"打开数据库成功");
            
            // 开启事物
            [db beginTransaction];
            
            // 插入数据
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            // 也可以在中途回滚 就是该次对数据库的操作不生效 通常中途一般不回滚
            [db rollback];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
            
            // 提交事物
            [db commit];
            
        }
        
    }];
  • 其实FMDB内部已经帮我们封装好,只需要调用FMDatabaseQueue对象方法 - (void)inTransaction:(void (^)(FMDatabase *db, BOOL *rollback))block
[baseQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        // 如果中途想回滚 就这样操作
        *rollback = YES;
        [db rollback];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
        [db executeUpdate:@"insert into t_table(name, age, score, data) values(?, ? , ?, ?)", @"jake", @12, @91.0, [NSData data]];
    }];
  • 下班了,不写了,大家如果发现有误,谢谢反馈给我😝😄

相关文章

网友评论

      本文标题:FMDB使用

      本文链接:https://www.haomeiwen.com/subject/nvvpettx.html