在学习sqlite的时候,发现OC中提供的API是面向过程的方式,如果在开发中用到,那么每次都会重复的去走这个流程,打开数据库,执行sql,细节上的处理等。于是就在sqlite3的基础上,进行了通用封装,在以后的开发中直接使用即可,提高开发效率。
源代码托管:https://github.com/zhangint/OCSQLite/tree/master
该封装只是针对通用的接口和使用方式,使用起来也比较简单,SQL语句,数据类型,数据值即可。
1.默认表的第一列为主键,创建表的时候需要注意。
2.如若有什么特殊功能或者细节控制,则该接口并不适用。
3.并不提供线程安全保证,需要用户自己进行控制。
查询效果:
插入效果:
接口说明:
为了满足多行多列数据的插入和查询,采用了二位数组的方式,当某一列的数据值为空时,需填充[NSNull null];
直接贴头文件内容吧,描述的也很清晰
内部定义数据说明
//sqlite支持的5种数据类型typedef NS_ENUM(NSInteger,DataType){ DTNulL = 0,//NulL DTINT,//整数 DTREAL,//浮点数 DTTEXT,//文本数据 DTBLOB //二进制数据};
头文件接口
//@brIEf:打开数据库文件//@param:dbfile 数据库文件路径//@return: 0 成功 其它 失败的错误码- (NSInteger)openDB:(Nsstring *)dbfile;//@brIEf:关闭数据库连接//@return: YES 成功 NO 失败- (NSInteger)closeDB;//@breif: sql命令,返回执行状态//@return: 0 成功// 其它 错误码//@attention: 主要执行查询,状态获取等- (NSInteger)execsql:(Nsstring *)sql;//@brIEf: 执行SQL查询语句//@param: dataType 指定查询返回的数据类型(注意需为DataType的枚举值)//@return: 返回为双重数组,第一层为一行数据封装,第二层为列数据封装- (NSArray<NSArray *> *)sqlquery:(Nsstring *)sql dataType:(NSArray<NSNumber *> *)dataType;//@brIEf: 数据插入//@param: sql 插入的SQL语句// data 绑定的值,而为数组形式,先封装一行数据,然后再封装// datatype 每一列数据的值//@return: >=0 影响的行数// -1 失败//@attention: 内部不检测值和类型是否匹配,需用户自己校验- (NSInteger)sqlInsert:(Nsstring*)sql data:(NSArray<NSArray *> *)data datatype:(NSArray *)datatype;//@brIEf: 根据错误码,返回错误描述信息- (Nsstring *)lastError:(NSInteger)errcode;4.测试用例
1.多行数据插入
- (voID)insertClicked:(ID)sender{ //在插入数据的时候,先创建表 Nsstring *sql = @"create table if not exists test_table_1 \ (ID integer primary key autoincrement,\ name,\ passwd,\ address,\ age,\ photo,\ rank)"; NSLog(@"create table status:%ld",[_dbcon execsql:sql]); //构造一行的数据 NSMutableArray *rowData_1 = [[NSMutableArray alloc] init]; [rowData_1 addobject:@"zhangint"]; [rowData_1 addobject:@"123456"]; [rowData_1 addobject:@"chengdu"]; [rowData_1 addobject:[NSNumber numberWithInt:25]]; Nsstring *pic1 = [[NSBundle mainBundle] pathForResource:@"zhangint" ofType:nil]; NSData *pic1_data = [NSData dataWithContentsOffile:pic1]; unsigned char* msg = (unsigned char*)[pic1_data bytes]; [rowData_1 addobject:pic1_data]; //二进制 [rowData_1 addobject:[NSNumber numberWithfloat:2.3]]; //浮点数 NSMutableArray *rowData_2 = [[NSMutableArray alloc] init]; [rowData_2 addobject:@"love dog"]; [rowData_2 addobject:@"56789"]; [rowData_2 addobject:[NSNull null]]; //string为空 [rowData_2 addobject:[NSNumber numberWithInt:33]]; Nsstring *pic2 = [[NSBundle mainBundle] pathForResource:@"xiaoyu" ofType:nil]; NSData *pic2_data = [NSData dataWithContentsOffile:pic2]; [rowData_2 addobject:pic2_data]; [rowData_2 addobject:[NSNumber numberWithfloat:3.3]]; NSMutableArray *rowData_3 = [[NSMutableArray alloc] init]; [rowData_3 addobject:@"xiaoxiaoxiao"]; [rowData_3 addobject:@"9990"]; [rowData_3 addobject:@"beijing"]; [rowData_3 addobject:[NSNumber numberWithInt:32]]; [rowData_3 addobject:[NSNull null]]; //二进制位空 [rowData_3 addobject:[NSNumber numberWithfloat:5.4]]; //数据值的初始化 NSArray *tableArr = [[NSArray alloc] initWithObjects:rowData_1,rowData_2,rowData_3,nil]; //数据类型的初始化 NSArray *dataType = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:DTTEXT],[NSNumber numberWithInt:DTTEXT],[NSNumber numberWithInt:DTINT],[NSNumber numberWithInt:DTBLOB],[NSNumber numberWithInt:DTREAL],nil]; Nsstring *insertsql = @"insert into test_table_1 values(null,?,?)"; NSLog(@"insert res:%ld",[_dbcon sqlInsert:insertsql data:tableArr datatype:dataType]);
2.数据查询
- (voID) searchClicked:(ID)sender{ Nsstring *sql = @"select * from test_table_1"; NSArray *dataType = [[NSArray alloc] initWithObjects:[NSNumber numberWithBool:DTINT],nil]; NSArray<NSArray *> *searchRes; searchRes = [_dbcon sqlquery:sql dataType:dataType]; NSInteger rows = [searchRes count]; NSLog(@"search rows:%ld",rows); for (int i=0; i<rows; i++) { NSArray *rowData = searchRes[i]; NSNumber *IDnum = rowData[0]; Nsstring *name = rowData[1]; Nsstring *passed = rowData[2]; Nsstring *address = rowData[3]; NSNumber *age = rowData[4]; //NSData *img = rowData[5]; NSNumber *rank = rowData[6]; NSLog(@"ID:%d name:%@ passwd:%@ address:%@ age:%d photo not show rank:%.1f",IDnum.intValue,name,passed,address,age.intValue,rank.floatValue); } _searchRes = searchRes;5.源代码
头文件:sqliteInter.h
//// sqliteInter.h// sqlitePro//// Created by zp on 15/12/26.// copyright © 2015年 ZP. All rights reserved.////@brIEf: sqlite通用接口封装//@attention: 1.本身并不提供线程安全,用户可以通过Serial dispatch Queue的方式,保证安全可靠访问// 2.只是对通用的使用方式进行了封装,很多细节或者特殊的使用方式并未覆盖#import <Foundation/Foundation.h>#import <sqlite3.h>//sqlite支持的5种数据类型typedef NS_ENUM(NSInteger,//文本数据 DTBLOB //二进制数据};@interface sqliteInter : NSObject//错误码@property (assign,nonatomic) NSInteger lastErrCode;//@brIEf:打开数据库文件//@param:dbfile 数据库文件路径//@return: 0 成功 其它 失败的错误码- (NSInteger)openDB:(Nsstring *)dbfile;//@brIEf:关闭数据库连接//@return: YES 成功 NO 失败- (NSInteger)closeDB;//@breif: sql命令,返回执行状态//@return: 0 成功// 其它 错误码//@attention: 主要执行查询,状态获取等- (NSInteger)execsql:(Nsstring *)sql;//@brIEf: 执行SQL查询语句//@param: dataType 指定查询返回的数据类型(注意需为DataType的枚举值)//@return: 返回为双重数组,第一层为一行数据封装,第二层为列数据封装- (NSArray<NSArray *> *)sqlquery:(Nsstring *)sql dataType:(NSArray<NSNumber *> *)dataType;//@brIEf: 数据插入//@param: sql 插入的SQL语句// data 绑定的值,而为数组形式,先封装一行数据,然后再封装// datatype 每一列数据的值//@return: >=0 影响的行数// -1 失败//@attention: 内部不检测值和类型是否匹配,需用户自己校验- (NSInteger)sqlInsert:(Nsstring*)sql data:(NSArray<NSArray *> *)data datatype:(NSArray *)datatype;//@brIEf: 根据错误码,返回错误描述信息- (Nsstring *)lastError:(NSInteger)errcode;@end
实现文件
sqliteInter.m
//// sqliteInter.m// sqlitePro//// Created by zp on 15/12/26.// copyright © 2015年 ZP. All rights reserved.///**@brIEf:sqlite数据接口封装,方便复用 * * */#import "sqliteInter.h"@interface sqliteInter ()//注意:sqlite3 为struct类型,不能用strong属性@property (assign,nonatomic) sqlite3 *database;@property (assign,nonatomic) sqlite3_stmt *stmt;@end@implementation sqliteInter- (NSInteger)openDB:(Nsstring *)dbfile{ //如果数据库已经打开,则先关闭 if (_database) { _lastErrCode = [self closeDB]; if (_lastErrCode != sqlITE_OK) { _lastErrCode = 0; return 0; } } _lastErrCode = sqlite3_open([dbfile UTF8String],&_database); return _lastErrCode;}- (NSInteger)closeDB{ if (_database) { NSInteger num = 0; //会关闭2次,2次失败,则失败 while (num < 2) { _lastErrCode = sqlite3_close(_database); //关闭成功 if (sqlITE_OK == _lastErrCode) { _database = nil; break; } sqlite3_finalize(_stmt); num++; } } return _lastErrCode;}- (NSInteger)execsql:(Nsstring *)sql{ //这个地方并不校验 _database == nil,errorcode 会有描述 _lastErrCode = sqlite3_exec(_database,[sql UTF8String],NulL,NulL); //返回错误码 return _lastErrCode;}- (NSArray<NSArray *> *)sqlquery:(Nsstring *)sql dataType:(NSArray<NSNumber *> *)dataType{ NSMutableArray *dataSet = [[NSMutableArray alloc] init]; NSInteger preRes = sqlite3_prepare_v2(_database,-1,&_stmt,nil); if (preRes == sqlITE_OK) { while (sqlite3_step(_stmt) == sqlITE_ROW) { NSMutableArray *dataArr = [[NSMutableArray alloc] init]; int colNum = sqlite3_data_count(_stmt); //获取列的数量 for (int i=0; i<colNum; i++) { [dataArr addobject:[self get_col_data:dataType[i].intValue statement:_stmt col:i]]; } [dataSet addobject:dataArr]; } } sqlite3_finalize(_stmt); return dataSet;}- (ID) get_col_data:(DataType)dbtype statement:(sqlite3_stmt *)stmt col:(NSInteger)col{ switch (dbtype) { case DTNulL: return [NSNull null]; break; case DTINT:{ //(int)col 强制转化,避免警告 NSNumber *number = [NSNumber numberWithInt:sqlite3_column_int(stmt,(int)col)]; return number; break; } case DTREAL:{ NSNumber *number = [NSNumber numberWithfloat:sqlite3_column_double(stmt,(int)col)]; return number; } case DTTEXT:{ Nsstring *cellData; char* str = (char*)(char*)sqlite3_column_text(stmt,(int)col); if (str != NulL) { cellData = [Nsstring stringWithFormat:@"%s",str]; } else { //当为空的时候,为一个空对象 cellData = @""; } return cellData; } //二进制的处理 case DTBLOB:{ NSInteger len = sqlite3_column_bytes(stmt,(int)col); NSData *cellData = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt,(int)col) length:len]; return cellData; } default: break; } return [NSNull null];}- (NSInteger)sqlInsert:(Nsstring*)sql data:(NSArray<NSArray *> *)data datatype:(NSArray *)datatype{ NSInteger effectNum = 0; int preStatus = sqlite3_prepare_v2(_database,NulL); if (preStatus == sqlITE_OK) { for (int i=0; i<data.count; i++) { NSArray *rowData = data[i]; for (int col=0; col<rowData.count; coL++) { NSNumber *type = datatype[col]; switch (type.intValue) { case DTNulL: sqlite3_bind_null(_stmt,col+1); break; case DTINT:{ NSNumber *number = rowData[col]; sqlite3_bind_int(_stmt,col+1,number.intValue); break; } case DTREAL:{ NSNumber *real = rowData[col]; sqlite3_bind_double(_stmt,real.floatValue); break; } case DTTEXT:{ Nsstring *str; if (rowData[col] == [NSNull null]) { str = @""; } else { str = rowData[col]; } sqlite3_bind_text(_stmt,[str UTF8String],NulL); break; } case DTBLOB:{ NSData *msg; if (rowData[col] == [NSNull null]) { msg = [[NSData alloc] initWithBytes:@"" length:1]; } else { msg = rowData[col]; } sqlite3_bind_blob(_stmt,[msg bytes],(int)[msg length],NulL); break; } default: break; } /*switch */ } //for if (sqlite3_step(_stmt) == sqlITE_DONE) { effectNum++; } //需要重置statement sqlite3_reset(_stmt); } /*for*/ } /*if*/ sqlite3_finalize(_stmt); return effectNum; //这种用法不对 //return sqlite3_changes(_database);}- (Nsstring *)lastError:(NSInteger)errcode{ return [Nsstring stringWithUTF8String:sqlite3_errstr((int)errcode)];}@end总结
以上是内存溢出为你收集整理的5.SQLite面相对象通用封装全部内容,希望文章能够帮你解决5.SQLite面相对象通用封装所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)