Transform Sqliteplugin plug-in, unified management with Fmdb

Source: Internet
Author: User

Next blog:

Database locked problem for hybrid application

Ours is the hybrid application, based on the Cordova. Do the first version of the time inexperienced, the original part with Fmdb access to the database, the Web Part of a direct search for a sqliteplugin. Early on, the native code and JS access to the database are staggered, so there is no problem. But now, some scenes need 2 side to access the database together, because SQLite does not support concurrent write, it produced database locked problem

In fact, looking back, if in the first version on the basis of Fmdb to write a Cordova plug-in to provide to JS call is very easy, but now re-transformation is a lot of trouble, because the business code has been a lot of calls to the Sqliteplugin JS interface, So the JS part of Sqliteplugin must be unable to move, otherwise the business code will have to change. So the final decision to adopt the scheme is to sqliteplugin the original part of the re-use Fmdb to achieve once. This application of the native code, and Cordova plug-ins, are used fmdatabasequeue to manage, there will be no lock library phenomenon

The process of transformation is not very difficult, mainly 2 chunks:

1, the sqliteplugin operation of the database code, such as Sqlite3_step, with the Fmdb provided by the API to replace

2, through the debug, figure out the JS part and the original code part of the parameters and return values, and then the interface to ensure that the correct processing of JS parameters, and return the same as the original implementation of the return value

Read through all the code and discover that the core part is the method:

-(cdvpluginresult*) Executesqlwithdict: (nsmutabledictionary*) options

Options is the parameters of the JS Pass, there are sql,params,query,qid these 4 key, so we call the Fmdb API required parameters, is also taken from it. And the last return value of this method must contain Qid,type,result,error, specifically, QID is returned as is, the type may be success or error,result must contain rows, That is, the result of the Select query (in fact there are rowaffected and some other keys, but it is not used to check the discovery, so the new implementation ignores these keys)

Once the above parameters and return values are clear, the remainder is re-implemented. Sqliteplugin original code has about 1000 lines, do not have to call Sqlite3 API, there are processing type conversion, parameter binding and other general actions, these things have been done in Fmdb, so the use of fmdb re-implementation is very simple. After the transformation of the code is only 200 lines, the core is the method:

-(cdvpluginresult*) Executesqlwithdict: (nsmutabledictionary*) options{nsstring *sql = [Options objectforkey:@ "SQL"];        Nsarray *params = [Options objectforkey:@ "params"];        Nsmutablearray *resultrows = [nsmutablearray array];//query result set __block nsdictionary *error = nil; [DBHelper dooperation:^ (Fmdatabase *db) {if ([[[SQL LowerCaseString] hasprefix:@ "select"]) {fmresultset *rs = [db Executequer                        Y:sql Withargumentsinarray:params];             if (!rs) {error = @{@ "code": [NSNumber numberwithint:[db LastErrorCode]], @ "message": [DB Lasterrormessage]};                }else{while ([Rs next]) {[Resultrows addobject:[rs resultdictionary]];            } [Rs Close];            }}else{BOOL result = [db Executeupdate:sql withargumentsinarray:params]; if (!result) {error = @{@ "code": [NSNumber numberwithint:[db LastErrOrcode]], @ "message": [DB Lasterrormessage]};        }        }    }];    if (error) {return [Cdvpluginresult resultwithstatus:cdvcommandstatus_error messageasdictionary:error];    } nsdictionary *cdvresult = @{@ "Rows": Resultrows}; return [Cdvpluginresult RESULTWITHSTATUS:CDVCOMMANDSTATUS_OK messageasdictionary:cdvresult];}

As long as you are familiar with Fmdb API, the above code is very straightforward, there is nothing to specifically explain.

In addition, this plugin holds an instance variable of DBHelper:

{    ylsdatabasehelper *dbhelper;} -(cdvplugin*) Initwithwebview: (uiwebview*) thewebview{self    = (sqliteplugin*) [Super Initwithwebview:thewebview] ;    if (self) {        dbhelper = [Ylsdatabasehelper sharedinstance];    }    return self;}

This ylsdatabasehelper is a singleton, the native code and the plugin that accesses the database through this unique portal, thus guaranteeing no concurrent writes (Fmdatabasequeue's internal mechanism). If this dbhelper is not a singleton, but there are multiple instances, it is not possible to avoid the database locked

@implementation ylsdatabasehelper{    fmdatabasequeue* queue;} -(ID) init{self    = [super init];    if (self) {        NSString *dbfilepath = [Ylsglobalutils Getdatabasefilepath];        Queue = [Fmdatabasequeue Databasequeuewithpath:dbfilepath];    }    return self;} + (ylsdatabasehelper*) sharedinstance{    static dispatch_once_t pred = 0;    __strong static id _sharedobject = nil;    Dispatch_once (&pred, ^{        _sharedobject = [[Self alloc] init];    });    return _sharedobject;} + (void) refreshdatabasefile{    ylsdatabasehelper *instance = [self sharedinstance];    [Instance Dorefresh];} -(void) dorefresh{    nsstring *dbfilepath = [Ylsglobalutils Getdatabasefilepath];    Queue = [Fmdatabasequeue Databasequeuewithpath:dbfilepath];} -(void) Dooperation: (void (^) (fmdatabase*)) block{    [Queue indatabase:^ (Fmdatabase *db) {        block (db);    }];} @end

After this transformation, the JS section has no effect, the Web business code does not need to be modified. But after all, is the transformation, in fact, if in the first version can be aware of this problem, you can write a plugin directly, do not need to introduce sqliteplugin, and then the JS part of the plugin can be a lot simpler

Transform Sqliteplugin plug-in, unified management with Fmdb

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.