iOS之Sqlite3封装.docx

上传人:b****5 文档编号:6187187 上传时间:2023-01-04 格式:DOCX 页数:20 大小:297.87KB
下载 相关 举报
iOS之Sqlite3封装.docx_第1页
第1页 / 共20页
iOS之Sqlite3封装.docx_第2页
第2页 / 共20页
iOS之Sqlite3封装.docx_第3页
第3页 / 共20页
iOS之Sqlite3封装.docx_第4页
第4页 / 共20页
iOS之Sqlite3封装.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

iOS之Sqlite3封装.docx

《iOS之Sqlite3封装.docx》由会员分享,可在线阅读,更多相关《iOS之Sqlite3封装.docx(20页珍藏版)》请在冰豆网上搜索。

iOS之Sqlite3封装.docx

iOS之Sqlite3封装

iOS之Sqlite3封装

实例项目简介

这个实例主要是封装sqlite3数据库工具,并用这个工具实现记录、删除、修改、查询学生信息的功能,另外一个附属的功能就是根据学生的姓名首字母分组并添加索引。

对于数据库,我做了两层封装。

第一层是对数据库的基本操作进行抽象,第二层是对学生数据的操作进行抽象。

这种分层的思想不仅能使处于底层的功能得到多次重用,调高效率;而且这样做逻辑清晰,易于定位问题,有益于维护与跟新。

四、实例项目分析

1、首先抽象出数据库基本操作工具类,而数据库的基本操作有:

打开、关闭、建表、增、删、改、查……基于这些操作,我封装出如下五个方法来提供数据库的操作:

*打开数据库

*

*@parampath数据库路径

*@paramsuccess打开成功的回调

*@paramfalure打开失败的回调

*/

+(void)openDBPath:

(NSString*)pathsuccesefulBlock:

(void(^)(sqlite3*db))successandFailureBlock:

(void(^)(NSString*msg))failure

{

sqlite3*database=NULL;

intresult=sqlite3_open(path.UTF8String,&database);

if(result==SQLITE_OK){

if(success){

success(database);

}

}

else

{

if(failure){

constchar*msg=sqlite3_errmsg(database);

failure([NSStringstringWithUTF8String:

msg]);

}

if(database){

[selfcloseDB:

databasesuccesefulBlock:

nilandFailureBlock:

nil];

}

}

}

/**

*关闭数据库

*

*@paramdatabase数据库链接

*@paramsuccese成功的回调

*@paramfailure失败的回调

*/

+(void)closeDB:

(sqlite3*)databasesuccesefulBlock:

(void(^)())succeseandFailureBlock:

(void(^)(NSString*msg))failure

{

intresult=sqlite3_close(database);

if(result==SQLITE_OK){

if(succese){

succese();

}

}

else

{

if(failure){

failure([NSStringstringWithUTF8String:

sqlite3_errmsg(database)]);

}

}

}

/**

*执行SQL语句(不适应查询语句和blob(NSData)二进制数据类型的操作)

*

*@paramsqStrSQL语句

*@paramdatabase数据库链接

*@paramsuccese成功的回调

*@paramfailure失败的回调

*/

+(void)executeSql:

(NSString*)sqStrtoDatabase:

(sqlite3*)databasesuccesefulBlock:

(void(^)())succeseandFailureBlock:

(void(^)(NSString*msg))failure

{

DebugLog(@"%@",sqStr);

char*msg=NULL;

intresult=sqlite3_exec(database,sqStr.UTF8String,NULL,NULL,&msg);

if(result==SQLITE_OK){

if(succese){

succese();

}

}

else

{

if(failure){

failure([NSStringstringWithUTF8String:

msg]);

}

}

}

/**

*准备需要sqlite3_stmt结果集的SQL语句

*

*@paramsqStrSQL语句

*@paramdatabase数据库连接

*@paramsuccese成功的回调

*@paramfailure失败的回调

*/

+(void)prepareSql:

(NSString*)sqStrfromDatabase:

(sqlite3*)databasesuccesefulBlock:

(void(^)(sqlite3_stmt*stmt))succeseandFailureBlock:

(void(^)(NSString*msg))failure

{

DebugLog(@"%@",sqStr);

sqlite3_stmt*stmt=NULL;

intresult=sqlite3_prepare_v2(database,sqStr.UTF8String,-1,&stmt,NULL);

if(result==SQLITE_OK){

if(succese){

succese(stmt);

}

}

else

{

if(failure){

failure(@"SQL语句是非法的。

");

}

}

}

2、接着就是抽象学生数据功能类了。

根据需要我抽象出了如下五个方法

/**

*获取所有学生

*

*@paramcallBack回调

*/

+(void)getAllStudents:

(void(^)(NSArray*students,NSString*msg))callBack;

/**

*添加学生

*

*@paramstudentModel学生模型

*@paramsuccese添加成功回调

*@paramfailure添加失败回调

*/

+(void)addStudent:

(StudentModel*)studentModelsuccesefulBlock:

(void(^)(StudentModel*studentModel))succeseandFailureBlock:

(void(^)(NSString*msg))failure;

/**

*更新学生

*

*@paramstudentModel学生模型

*@paramsuccese更新成功回调

*@paramfailure更新失败回调

*/

+(void)updateStudent:

(StudentModel*)studentModelsuccesefulBlock:

(void(^)(StudentModel*studentModel))succeseandFailureBlock:

(void(^)(NSString*msg))failure;

/**

*按条件搜索学生

*

*@paramcondition条件

*@paramcallBack搜索回调

*/

+(void)searchStudents:

(NSString*)conditionandCallBack:

(void(^)(NSArray*students,NSString*msg))callBack;

/**

*删除学生

*

*@paramstudentModel学生模型

*@paramsuccese删除成功回调

*@paramfailure删除失败回调

*/

+(void)deleteStudent:

(StudentModel*)studentModelsuccesefulBlock:

(void(^)(StudentModel*studentModel))succeseandFailureBlock:

(void(^)(NSString*msg))failure;

细节分析

-由于该功能类都是使用类方法,所以不能以实例变量来存储数据,因此声明全局变量staticsqlite3*database来存储数据库的链接,并以static关键字修饰来避免其他源文件对其访问。

-类方法initialize是在手动调用累中任何方法前调用一次,所以在这个方法中打开数据库并创建学生表是非常合适的。

/**

*在手动调用类里的任何方法前自动调用一次

*/

+(void)initialize

{

[SqliteDBAccessopenDBPath:

SqlitePathStrsuccesefulBlock:

^(sqlite3*db){

DebugLog(@"数据库打开成功!

");

[SqliteDBAccessexecuteSql:

[NSStringstringWithFormat:

@"CREATETABLEIFNOTEXISTS%@(identifierintegerPRIMARYKEYAUTOINCREMENT,nametextNOTNULL,studentNumbertextNOTNULLUNIQUE,photoblob,ageintegerNOTNULL,addresstext,describetext);",StudentTableName]toDatabase:

dbsuccesefulBlock:

^{

database=db;

DebugLog(@"学生表创建成功!

");

}andFailureBlock:

^(NSString*msg){

DebugLog(@"学生表创建失败,%@",msg);

}];

}andFailureBlock:

^(NSString*msg){

DebugLog(@"数据库打开失败,%@",msg);

}];

}

在学生数据功能类的内部可以封装一个不公开的方法来从sqlite3_stmt结果集中获取学生模型对象

/**

*从sqlite3_stmt中获取学生数据

*

*@paramstmtsqlite3_stmt结果集

*

*@return学生数组

*/

+(NSArray*)getStudentsFromStatement:

(sqlite3_stmt*)stmt

{

NSMutableArray*students=[NSMutableArrayarrayWithCapacity:

1];

StudentModel*studentModel;

while(sqlite3_step(stmt)==SQLITE_ROW){

studentModel=[[StudentModelalloc]init];

studentModel.identifier=sqlite3_column_int(stmt,0);

char*name=(char*)sqlite3_column_text(stmt,1);

char*studentNumber=(char*)sqlite3_column_text(stmt,2);

void*photo=(void*)sqlite3_column_blob(stmt,3);

studentModel.name=name?

[NSStringstringWithUTF8String:

name]:

nil;

studentModel.studentNumber=studentNumber?

[NSStringstringWithUTF8String:

studentNumber]:

nil;

studentModel.photo=photo?

[UIImageimageWithData:

[NSDatadataWithBytes:

photolength:

sqlite3_column_bytes(stmt,3)]]:

nil;

studentModel.age=sqlite3_column_int(stmt,4);

char*address=(char*)sqlite3_column_text(stmt,5);

char*describe=(char*)sqlite3_column_text(stmt,6);

studentModel.address=address?

[NSStringstringWithUTF8String:

address]:

nil;

studentModel.describe=describe?

[NSStringstringWithUTF8String:

describe]:

nil;

[studentsaddObject:

studentModel];

}

returnstudents;

}

由于表中存在二进制数据,所以插入跟新二进制数据时使用sqlite3_exec函数执行SQL语句是有问题的,需要使用sqlite3_step函数来执行SQL语句。

/**

*更新学生

*

*@paramstudentModel学生模型

*@paramsuccese更新成功回调

*@paramfailure更新失败回调

*/

+(void)updateStudent:

(StudentModel*)studentModelsuccesefulBlock:

(void(^)(StudentModel*studentModel))succeseandFailureBlock:

(void(^)(NSString*msg))failure

{

[SqliteDBAccessprepareSql:

[NSStringstringWithFormat:

@"UPDATE%@SETname=?

studentNumber=?

photo=?

age=?

address=?

describe=?

WHEREidentifier=?

;",StudentTableName]fromDatabase:

databasesuccesefulBlock:

^(sqlite3_stmt*stmt){

NSData*data=UIImagePNGRepresentation(studentModel.photo);

sqlite3_bind_text(stmt,1,studentModel.name.UTF8String,-1,NULL);

sqlite3_bind_text(stmt,2,studentModel.studentNumber.UTF8String,-1,NULL);

sqlite3_bind_blob(stmt,3,[databytes],(int)[datalength],NULL);

sqlite3_bind_int(stmt,4,studentModel.age);

sqlite3_bind_text(stmt,5,studentModel.address.UTF8String,-1,NULL);

sqlite3_bind_text(stmt,6,studentModel.describe.UTF8String,-1,NULL);

sqlite3_bind_int(stmt,7,studentModel.identifier);

//执行完成

if(sqlite3_step(stmt)==SQLITE_DONE){

if(succese){

succese(studentModel);

}

}

else

{

if(failure){

failure([NSStringstringWithFormat:

@"更新学生失败,%@",[NSStringstringWithUTF8String:

sqlite3_errmsg(database)]]);

}

}

//在遍历完结果集后,调用sqlite3_finalize以释放和预编译的语句相关的资源。

sqlite3_finalize(stmt);

}andFailureBlock:

^(NSString*msg){

if(failure){

failure([NSStringstringWithFormat:

@"更新学生失败,%@",msg]);

}

}];

}

五、问题与补充

1.sqlite3事务:

是并发控制的基本单位。

所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。

例如,银行转账工作:

从一个账号扣款并使另一个账号增款,这两个操作要么都执行,要么都不执行。

所以,应该把它们看成一个事务。

事务是数据库维护数据一致性的单位,在每个事务结束时,都能保持数据一致性。

针对上面的描述可以看出,事务的提出主要是为了解决并发情况下保持数据一致性的问题。

事务的语句:

-开始事物:

BEGINTRANSACTION

-提交事物:

COMMITTRANSACTION

-回滚事务:

ROLLBACKTRANSACTION

项目中添加学生数据的时候,并没有设置identifer主键,但是主键是有用的,在插入成功后需要查出来,因此添加学生就涉及两步操作:

插入数据,查询数据。

而且这两个操作必须要同时成功才能算是学生添加成功。

所以在这里,我就开启一个事务,先插入学生数据,再查询此学生数据,只要有一个步骤发生错误就回滚事务,全部成功则提交事务:

/**

*添加学生

*

*@paramstudentModel学生模型

*@paramsuccese添加成功回调

*@paramfailure添加失败回调

*/

+(void)addStudent:

(StudentModel*)studentModelsuccesefulBlock:

(void(^)(StudentModel*studentModel))succeseandFailureBlock:

(void(^)(NSString*msg))failure

{

//开启事务

[SqliteDBAccessexecuteSql:

@"BEGINTRANSACTION"toDatabase:

databasesuccesefulBlock:

^{

DebugLog(@"事务启动成功!

");

[SqliteDBAccessprepareSql:

[NSStringstringWithFormat:

@"INSERTINTO%@(name,studentNumber,photo,age,address,describe)VALUES(?

?

?

?

?

?

);",StudentTableName]fromDatabase:

databasesuccesefulBlock:

^(sqlite3_stmt*stmt){

NSData*data=UIImagePNGRepresentation(studentModel.photo);

sqlite3_bind_text(stmt,1,studentModel.name.UTF8String,-1,NULL);

sqlite3_bind_text(stmt,2,studentModel.studentNumber.UTF8String,-1,NULL);

sqlite3_bind_blob(stmt,3,[databytes],(int)[datalength],NULL);

sqlite3_bind_int(stmt,4,studentModel.age);

sqlite3_bind_text(stmt,5,studentModel.address.UTF8String,-1,NULL);

sqlite3_bind_text(stmt,6,studentModel.describe.UTF8String,-1,NULL);

if(sqlite3_step(stmt)==SQLITE_DONE){

[SqliteDBAccessprepareSql:

[NSStringstringWithFormat:

@"SELECT*FROM%@WHEREstudentNumber=?

;",StudentTableName]fromDatabase:

databasesuccesefulBlock:

^(sqlite3_stmt*stmt){

sqlite3_bind_text(stmt,1,studentModel.studentNumber.UTF8String,-1,NULL);

StudentModel*model=[[selfgetStudentsFromStatement:

stmt]firstObject];

if(studentModel){

studentModel.identifier=model.identifier;

if(succese){

succese(studentModel);

}

//提交事务

[SqliteDBAccessexecuteSql:

@"COMMITTRANSACTION"toDatabase:

databasesuccesefulBlock:

^{

DebugLog(@"提交事务成功!

");

}andFailureBlock:

^(NSString*msg){

DebugLog(@"提交事务失败:

%@",msg);

}];

}

else

{

//回滚事务

[SqliteDBAccessexecuteSql:

@"ROLLBACKTRANSACTION"toDatabase:

databasesuccesefulBlock:

^{

DebugLog(@"回滚成功!

");

}andFailureBlock:

^(NSString*msg){

DebugLog(@"回滚失败:

%@",msg);

}];

}

//在遍历完结果集后,调用sqlite3_finalize以释放和预编译的语句相关的资源。

sqlite3_finalize(stmt);

}andFailureBlock:

^(

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 起诉状

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1