【轉】Phonegap離線調用SQLite數據庫文件

按:不可多得的好文章,轉過來以避免源丟失
文章來源: http://liuwei.co/index.php/default/The-quickest-way-to-execute-many-sql-for-import-database.html
 

客戶須要作離線App, 也就是說如今須要將Sqlserver數據庫中現有的數據所有初始化至App本地數據庫。若是一條條insert,一共有接近70萬條數據。顯然使用Web sql 5M的容量限制沒法知足要求。
因而採用PhoneGap SQLitePlugin,地址: https://github.com/lite4cordova/Cordova-SQLitePlugin爲項目添加好插件以後,運行,帶來另外一個問題,執行insert語句依舊很慢。以後,便採用5000條語句使用一個事務的方式批量插入,對10萬條數據進行了測試,以下:

 

executeSqlBatch icount:0 insertSumCount:20 Time:3:00:29 PM GMT+08:00
 
executeSqlBatch icount:1 insertSumCount:20 Time:3:00:32 PM GMT+08:00
 
executeSqlBatch icount:2 insertSumCount:20 Time:3:00:39 PM GMT+08:00
 
executeSqlBatch icount:3 insertSumCount:20 Time:3:00:48 PM GMT+08:00
 
executeSqlBatch icount:4 insertSumCount:20 Time:3:01:01 PM GMT+08:00
 
executeSqlBatch icount:5 insertSumCount:20 Time:3:01:16 PM GMT+08:00
 
executeSqlBatch icount:6 insertSumCount:20 Time:3:01:35 PM GMT+08:00
 
executeSqlBatch icount:7 insertSumCount:20 Time:3:01:58 PM GMT+08:00
 
executeSqlBatch icount:8 insertSumCount:20 Time:3:02:26 PM GMT+08:00
 
executeSqlBatch icount:9 insertSumCount:20 Time:3:02:56 PM GMT+08:00
 
executeSqlBatch icount:10 insertSumCount:20 Time:3:03:29 PM GMT+08:00
 
executeSqlBatch icount:11 insertSumCount:20 Time:3:04:06 PM GMT+08:00
 
executeSqlBatch icount:12 insertSumCount:20 Time:3:04:47 PM GMT+08:00
 
executeSqlBatch icount:13 insertSumCount:20 Time:3:05:31 PM GMT+08:00
 
executeSqlBatch icount:14 insertSumCount:20 Time:3:06:19 PM GMT+08:00
 
executeSqlBatch icount:15 insertSumCount:20 Time:3:07:08 PM GMT+08:00
 
executeSqlBatch icount:16 insertSumCount:20 Time:3:08:01 PM GMT+08:00
 
executeSqlBatch icount:17 insertSumCount:20 Time:3:08:58 PM GMT+08:00
 
executeSqlBatch icount:18 insertSumCount:20 Time:3:11:13 PM GMT+08:00
 
executeSqlBatch icount:19 insertSumCount:20 Time:3:12:17 PM GMT+08:00
 
executeSqlBatch icount:20 insertSumCount:20 Time:3:13:23 PM GMT+08:00

  

可 以看到,10萬條insert語句,採用每5000條語句提交一次事務的方式,一共花了12分54秒。並且每次執行時間比前一次時間要長,而且隨着數據量 越大,之後每次的執行時間將更長,由於sqlite採用的是文本形式的數據庫,每次對數據庫的操做都會進行I/O操做。顯然,如此漫長的等待時間,客戶是 難以接受的。javascript

最後解決的辦法是,將Sqlserver中現有的數據導出成sqlite數據庫文件,如xxx.db,以後將該文件放在程序 中,待App第一次啓動的時候,將該xxx.db數據庫文件拷貝到相應的目錄,如android默認是在/data/data/packagename /database目錄下,iphone默認是在/Applications/APP串/Documents目錄下。
因此,具體的解決辦法以下:php

Phonegap IOS版:html

1,將須要導入的數據庫文件拷貝到Resources目錄下.java

2, AppDelegate.m文件中添加以下代碼:android

- (void)createEditableCopyOfDatabaseIfNeeded {
// First, test for existence. BOOL success=NO;
BOOL success=NO;
NSString *dbFileName = @"import.db";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:dbFileName];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success){ NSLog(@"數據庫存在");
return;}
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbFileName];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}else {
NSLog(@"createEditableCopyOfDatabaseIfNeeded initialize success");
} }

  


在didFinishLaunchingWithOptions中調用:git

[self createEditableCopyOfDatabaseIfNeeded];

3, 在PhoneGap SQLitePlugin中打開數據庫的代碼爲:github

db = window.sqlitePlugin.openDatabase({name: "import.db"});

 

Phonegap Android版:sql

1,將須要導入的數據庫文件拷貝到res/raw目錄下.數據庫

2,添加DataBaseUtil.java文件
app

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
 
public class DataBaseUtil {
 
private Context context;
public static String dbName = "texonline.db";// 數據庫的名字
private static String DATABASE_PATH;// 數據庫在手機裏的路徑
 
public DataBaseUtil(Context context) {
this.context = context;
String packageName = context.getPackageName();
DATABASE_PATH="/data/data/"+packageName+"/databases/";
}
 
/**
* 判斷數據庫是否存在
*
* @return false or true
*/
public boolean checkDataBase() {
SQLiteDatabase db = null;
try {
String databaseFilename = DATABASE_PATH + dbName;
System.out.println("checkDataBase=>"+databaseFilename);
db = SQLiteDatabase.openDatabase(databaseFilename, null,SQLiteDatabase.OPEN_READONLY);
} catch (SQLiteException e) {
 
}
if (db != null) {
db.close();
}
return db != null ? true : false;
}
 
/**
* 複製數據庫到手機指定文件夾下
*
* @throws IOException
*/
public void copyDataBase() throws IOException {
String databaseFilenames = DATABASE_PATH + dbName;
File dir = new File(DATABASE_PATH);
if (!dir.exists())// 判斷文件夾是否存在,不存在就新建一個
dir.mkdir();
FileOutputStream os = new FileOutputStream(databaseFilenames);// 獲得數據庫文件的寫入流
InputStream is = context.getResources().openRawResource(R.raw.texonline);// 獲得數據庫文件的數據流
byte[] buffer = new byte[8192];
int count = 0;
while ((count = is.read(buffer)) > 0) {
os.write(buffer, 0, count);
os.flush();
}
is.close();
os.close();
System.out.println("copyDataBase success");
}
}

  


3,在繼承自DroidGap的activity裏添加以下方法,並在onCreate裏調用。

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Set by <content src="index.html" /> in config.xml
super.setIntegerProperty("loadUrlTimeoutValue", 60000);
super.loadUrl(Config.getStartUrl(),10000);
copyDataBaseToPhone();
}
 
private void copyDataBaseToPhone() {
DataBaseUtil util = new DataBaseUtil(this);
// 判斷數據庫是否存在
boolean dbExist = util.checkDataBase();
 
if (dbExist) {
Log.i("tag", "The database is exist.");
} else {// 不存在就把raw裏的數據庫寫入手機
try {
util.copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}

  


4,在PhoneGap SQLitePlugin中打開數據庫的代碼爲:

db = window.sqlitePlugin.openDatabase({name: "import.db"});
相關文章
相關標籤/搜索