• IOS中数据存储 sqlite3 的应用


       相比于服务器端的数据存储,IOS中几种数据存储的技术:

        (1)XML属性列表 —— PList
        (2)NSKeyedArchiver 归档
        (3)Preference(偏好设置)
        (4)SQLite3
        (5)Core Data(以面向对象的方式操作数据库SQLite)
         发现用数据库进行数据的存储和缓存,才是王道, 比较有心得的体会:虽然通过文件的方式进行存储,读写速度相对数据库存储较快,但是涉及大批量的数据时,在查询/管理/优化方面,数据库的优势明显会更大些.而且作为移动端,SQLite数据库在数据缓存方面的运用则尤为重要.
         工作之余,运用SQLite3的许多小知识点,写了一个小小的数据库增删改查操作,专门与sqlite3交互的个人信息管理类,直接上代码,望大牛指正:
     
       
                                                                                           底层架构图
     
     核心代码实现:
    (1) Services服务层封装
     PesonManager.h
    #import <Foundation/Foundation.h>
    #import "Person.h"
    
    @interface PersonManager : NSObject
    
    + (instancetype)sharedPersonManager;
    
    // 1. 新增用户
    - (void)addPerson:(Person *)person;
    
    // 2. 更新用户(关于主键,永远都不要去修改)
    - (void)updatePerson:(Person *)person;
    
    // 3. 删除用户,使用主键来删除指定用户
    - (void)removePerson:(NSInteger)personID;
    
    // 4. 列表用户,查询所有用户
    - (NSArray *)allPersons;
    
    @end

     PesonManager.m 

    #import "PersonManager.h"
    #import <sqlite3.h>
    #import "NSString+JH.h"
    
    // 全局变量
    static PersonManager *_instance;
    
    @interface PersonManager()
    {
        // 全局的数据库句柄
        sqlite3 *_db;
    }
    
    @end
    
    @implementation PersonManager
    
    #pragma mark - 单例的方法
    + (id)allocWithZone:(struct _NSZone *)zone
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
     
        return _instance;
    }
    
    + (instancetype)sharedPersonManager
    {
        if (_instance == nil) {
            _instance = [[PersonManager alloc] init];
        }
        
        return _instance;
    }
    
    #pragma mark - 类方法
    - (id)init
    {
        self = [super init];
        
        // 懒加载数据库连接及创建数据表
        if (self) {
            // 1. 打开数据库
            [self openDB];
            // 2. 创建数据表
            [self createTable];
        }
        
        return self;
    }
    
    #pragma mark 打开数据库
    - (void)openDB
    {
      
        NSString *dbPath = [@"T_Person.db" appendDocumentDir];
        _db = NULL;
        
        if (SQLITE_OK == sqlite3_open([dbPath UTF8String], &_db)) {
            NSLog(@"数据库打开成功");
        } else {
            NSLog(@"数据库打开失败");
        }
    }
    
    #pragma mark 单步执行SQL
    - (void)execSQL:(NSString *)sql message:(NSString *)message
    {
        char *errmsg = NULL;
        if (SQLITE_OK == sqlite3_exec(_db, [sql UTF8String], NULL, NULL, &errmsg)) {
            NSLog(@"%@成功!", message);
        } else {
            NSLog(@"%@失败 - %s", message, errmsg);
        }
    }
    
    #pragma mark 创建数据表
    - (void)createTable
    {
        NSString *sql = @"CREATE TABLE IF NOT EXISTS T_Person (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT, gender INTEGER, age INTEGER, height REAL)";
        
        [self execSQL:sql message:@"创建数据表"];
    }
    
    - (void)addPerson:(Person *)person
    {
    // 1. SQL NSString *sql = [NSString stringWithFormat:@"INSERT INTO T_Person (name, gender, age, height) VALUES ('%@', %d, %d, %f)", person.name, person.gender, person.age, person.height]; [self execSQL:sql message:@"新增个人记录"]; } // 2. 更新用户(关于主键,永远都不要去修改) - (void)updatePerson:(Person *)person where: (NSStirng *)where { NSString *sql = [NSString stringWithFormat:@"UPDATE T_Person SET name = '%@', gender = %d, age = %d, height = %f where %@", person.name, person.gender, person.age, person.height , where]; [self execSQL:sql message:@"更新个人记录"]; } // 3. 删除用户,使用主键来删除指定用户 - (void)removePerson:(NSInteger)personID { NSString *sql =[NSString stringWithFormat: @"delete * from T_Person where id =%@",personID]; [self execSQL:sql message:@"删除记录成功"]; } // 4. 列表用户,查询所有用户 - (NSArray *)allPersons { NSString *sql = @"SELECT id, name, age, gender, height FROM T_Person ORDER BY name"; sqlite3_stmt *stmt = NULL; NSMutableArray *arrayM = [NSMutableArray array]; NSMutableArray *persons = nil; if (SQLITE_OK == sqlite3_prepare_v2(_db, [sql UTF8String], -1, &stmt, NULL)) { persons = [NSMutableArray array]; while (SQLITE_ROW == sqlite3_step(stmt)) { int ID = sqlite3_column_int(stmt, 0); const unsigned char *name = sqlite3_column_text(stmt, 1); int age = sqlite3_column_int(stmt, 2); int gender = sqlite3_column_int(stmt, 3); CGFloat height = sqlite3_column_double(stmt, 4); // const unsigned char *直接输出看不出结果,需要转换 NSString *nameUTF8 = [NSString stringWithUTF8String:(const char *)name]; Person *p = [Person personWithID:ID name:nameUTF8 age:age gender:gender height:height]; [persons addObject:p]; } } else { NSLog(@"语法错误"); } return persons; } @end

     接下来在控制器里面封装模型取出相应数据即可,关于SQLite3中运用的知识点,总结如下:

    1.  sqlite3_open 打开数据库
        * 如果数据库已经存在,直接打开
        * 如果数据库不存在,新建一个空白的数据库(0KB),然后再打开
     
     2. 创建数据表
        * 定义数据操作SQL
        * 调用sqlite3_exec执行SQL
        提示:为了避免重复建表,可以在建表SQL中增加 IF NOT EXISTS
     
     3. 单步执行操作
        增/删/改/查数据
    
     4. 查询语句
     1> 准备SQL
     2> 检查SQL语句是否正确                     sqlite3_prepare_v2
     3> 单步执行,依次获取查询到的记录             SQLITE_ROW == sqlite3_step...
     4> 按照查询顺序,依次取出每一个字段的内容
         sqlite3_column_text 取字符串
         sqlite3_column_int 取整数
         sqlite3_column_double 取浮点数
     
     5.操作SQLite数据库需要5个方法
        sqlite3_open
        sqlite3_exec
     
        sqlite3_prepare_v2
        sqlite3_step
     
        sqlite3_column_text 取字符串
        sqlite3_column_int 取整数
        sqlite3_column_double 取浮点数
     两个枚举
        SQLITE_OK
        SQLITE_ROW

          当然,一般在实际开发中都会直接封装成一套数据库操作类,但是对于SQL结构化查询,无论是服务器开发,还是客户端开发,都是万变不离其中.最后,十分感谢大牛LF的讲解与分享.

  • 相关阅读:
    2.1 ArrayList 线程不安全,LinkedList 线程不安全,Vector 线程安全
    Mybatis详解(二)--动态代理(未集成Spring)
    3.2经典垃圾收集器
    3.垃圾收集器与内存分配
    6.类文件结构(Class结构)
    7.类加载机制
    spark实现从hbase中批量查询多个rowKey
    spark实现分页查询hbase
    查询mysql数据库的表名,主键
    redis退出异常:ERR Errors trying to SHUTDOWN. Check logs.
  • 原文地址:https://www.cnblogs.com/e8net/p/3732917.html
Copyright © 2020-2023  润新知