按:不可多得的好文章,转过来以免源丢失
 

客户需要做离线App, 也就是说现在需要将Sqlserver数据库中现有的数据全部初始化至App本地数据库。如果一条条insert,一共有接近70万条数据。显然使用Web sql 5M的容量限制无法满足要求。
于是采用PhoneGap SQLitePlugin,地址: https://github.com/lite4cordova/Cordova-SQLitePlugin为项目添加好插件之后,运行,带来另一个问题,执行insert语句依旧很慢。之后,便采用5000条语句使用一个事务的方式批量插入,对10万条数据进行了测试,如下:

  1. executeSqlBatch icount:0 insertSumCount:20 Time:3:00:29 PM GMT+08:00
  2.  
  3. executeSqlBatch icount:1 insertSumCount:20 Time:3:00:32 PM GMT+08:00
  4.  
  5. executeSqlBatch icount:2 insertSumCount:20 Time:3:00:39 PM GMT+08:00
  6.  
  7. executeSqlBatch icount:3 insertSumCount:20 Time:3:00:48 PM GMT+08:00
  8.  
  9. executeSqlBatch icount:4 insertSumCount:20 Time:3:01:01 PM GMT+08:00
  10.  
  11. executeSqlBatch icount:5 insertSumCount:20 Time:3:01:16 PM GMT+08:00
  12.  
  13. executeSqlBatch icount:6 insertSumCount:20 Time:3:01:35 PM GMT+08:00
  14.  
  15. executeSqlBatch icount:7 insertSumCount:20 Time:3:01:58 PM GMT+08:00
  16.  
  17. executeSqlBatch icount:8 insertSumCount:20 Time:3:02:26 PM GMT+08:00
  18.  
  19. executeSqlBatch icount:9 insertSumCount:20 Time:3:02:56 PM GMT+08:00
  20.  
  21. executeSqlBatch icount:10 insertSumCount:20 Time:3:03:29 PM GMT+08:00
  22.  
  23. executeSqlBatch icount:11 insertSumCount:20 Time:3:04:06 PM GMT+08:00
  24.  
  25. executeSqlBatch icount:12 insertSumCount:20 Time:3:04:47 PM GMT+08:00
  26.  
  27. executeSqlBatch icount:13 insertSumCount:20 Time:3:05:31 PM GMT+08:00
  28.  
  29. executeSqlBatch icount:14 insertSumCount:20 Time:3:06:19 PM GMT+08:00
  30.  
  31. executeSqlBatch icount:15 insertSumCount:20 Time:3:07:08 PM GMT+08:00
  32.  
  33. executeSqlBatch icount:16 insertSumCount:20 Time:3:08:01 PM GMT+08:00
  34.  
  35. executeSqlBatch icount:17 insertSumCount:20 Time:3:08:58 PM GMT+08:00
  36.  
  37. executeSqlBatch icount:18 insertSumCount:20 Time:3:11:13 PM GMT+08:00
  38.  
  39. executeSqlBatch icount:19 insertSumCount:20 Time:3:12:17 PM GMT+08:00
  40.  
  41. executeSqlBatch icount:20 insertSumCount:20 Time:3:13:23 PM GMT+08:00

  

可 以看到,10万条insert语句,采用每5000条语句提交一次事务的方式,一共花了12分54秒。而且每次执行时间比前一次时间要长,并且随着数据量 越大,以后每次的执行时间将更长,因为sqlite采用的是文本形式的数据库,每次对数据库的操作都会进行I/O操作。显然,如此漫长的等待时间,客户是 难以接受的。

最后解决的办法是,将Sqlserver中现有的数据导出成sqlite数据库文件,如xxx.db,之后将该文件放在程序 中,待App第一次启动的时候,将该xxx.db数据库文件拷贝到相应的目录,如android默认是在/data/data/packagename /database目录下,iphone默认是在/Applications/APP串/Documents目录下。
所以,具体的解决办法如下:

Phonegap IOS版:

1,将需要导入的数据库文件拷贝到Resources目录下.

2, AppDelegate.m文件中添加如下代码:

  1. - (void)createEditableCopyOfDatabaseIfNeeded {
  2. // First, test for existence. BOOL success=NO;
  3. BOOL success=NO;
  4. NSString *dbFileName = @"import.db";
  5. NSFileManager *fileManager = [NSFileManager defaultManager];
  6. NSError *error; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  7. NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:dbFileName];
  8. success = [fileManager fileExistsAtPath:writableDBPath];
  9. if (success){ NSLog(@"数据库存在");
  10. return;}
  11. // The writable database does not exist, so copy the default to the appropriate location.
  12. NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbFileName];
  13. success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
  14. if (!success) {
  15. NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
  16. }else {
  17. NSLog(@"createEditableCopyOfDatabaseIfNeeded initialize success");
  18. } }

  

在didFinishLaunchingWithOptions中调用:

  1. [self createEditableCopyOfDatabaseIfNeeded];

3, 在PhoneGap SQLitePlugin中打开数据库的代码为:

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

Phonegap Android版:

1,将需要导入的数据库文件拷贝到res/raw目录下.

2,添加DataBaseUtil.java文件

  1. import java.io.File;
  2. import java.io.FileOutputStream;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5.  
  6. import android.content.Context;
  7. import android.database.sqlite.SQLiteDatabase;
  8. import android.database.sqlite.SQLiteException;
  9.  
  10. public class DataBaseUtil {
  11.  
  12. private Context context;
  13. public static String dbName = "texonline.db";// 数据库的名字
  14. private static String DATABASE_PATH;// 数据库在手机里的路径
  15.  
  16. public DataBaseUtil(Context context) {
  17. this.context = context;
  18. String packageName = context.getPackageName();
  19. DATABASE_PATH="/data/data/"+packageName+"/databases/";
  20. }
  21.  
  22. /**
  23. * 判断数据库是否存在
  24. *
  25. * @return false or true
  26. */
  27. public boolean checkDataBase() {
  28. SQLiteDatabase db = null;
  29. try {
  30. String databaseFilename = DATABASE_PATH + dbName;
  31. System.out.println("checkDataBase=>"+databaseFilename);
  32. db = SQLiteDatabase.openDatabase(databaseFilename, null,SQLiteDatabase.OPEN_READONLY);
  33. } catch (SQLiteException e) {
  34.  
  35. }
  36. if (db != null) {
  37. db.close();
  38. }
  39. return db != null ? true : false;
  40. }
  41.  
  42. /**
  43. * 复制数据库到手机指定文件夹下
  44. *
  45. * @throws IOException
  46. */
  47. public void copyDataBase() throws IOException {
  48. String databaseFilenames = DATABASE_PATH + dbName;
  49. File dir = new File(DATABASE_PATH);
  50. if (!dir.exists())// 判断文件夹是否存在,不存在就新建一个
  51. dir.mkdir();
  52. FileOutputStream os = new FileOutputStream(databaseFilenames);// 得到数据库文件的写入流
  53. InputStream is = context.getResources().openRawResource(R.raw.texonline);// 得到数据库文件的数据流
  54. byte[] buffer = new byte[8192];
  55. int count = 0;
  56. while ((count = is.read(buffer)) > 0) {
  57. os.write(buffer, 0, count);
  58. os.flush();
  59. }
  60. is.close();
  61. os.close();
  62. System.out.println("copyDataBase success");
  63. }
  64. }

  

3,在继承自DroidGap的activity里添加如下方法,并在onCreate里调用。

  1. @Override
  2. public void onCreate(Bundle savedInstanceState)
  3. {
  4. super.onCreate(savedInstanceState);
  5. // Set by <content src="index.html" /> in config.xml
  6. super.setIntegerProperty("loadUrlTimeoutValue", 60000);
  7. super.loadUrl(Config.getStartUrl(),10000);
  8. copyDataBaseToPhone();
  9. }
  10.  
  11. private void copyDataBaseToPhone() {
  12. DataBaseUtil util = new DataBaseUtil(this);
  13. // 判断数据库是否存在
  14. boolean dbExist = util.checkDataBase();
  15.  
  16. if (dbExist) {
  17. Log.i("tag", "The database is exist.");
  18. } else {// 不存在就把raw里的数据库写入手机
  19. try {
  20. util.copyDataBase();
  21. } catch (IOException e) {
  22. throw new Error("Error copying database");
  23. }
  24. }
  25. }

  

4,在PhoneGap SQLitePlugin中打开数据库的代码为:

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

  

 

【转】Phonegap离线调用SQLite数据库文件的更多相关文章

  1. RT/Metro商店应用如何调用SQLite数据库

    RT/Metro商店应用如何调用SQLite数据库 使用前,要安装:SQLite for Windows Runtime (Windows 8.1)(一个VS插件).还有Visual C++ Runt ...

  2. Android虚拟机中的sqlite数据库文件

    Android虚拟机中的sqlite数据库文件 ①

  3. 修复 SQLite 数据库文件

    目 录 第1章 说明    1 1 下载SQLite Tools    1 2 运行    2 第1章 说明 笔者编写的一个程序,无法往 SQLite 数据库文件里写数据.使用SQLiteSpy打开该 ...

  4. SharedPreferences数据、openFileOutput文件、SQLite数据库文件存储位置

    在模拟器中: SharedPreferences将XML文件保存在/data/data/<package name>/shared_prefs目录下, openFileOutput方法将文 ...

  5. WEKA从sqlite数据库文件导入数据

    1.编写代码的方式 只需要在java工程中导入weka.jar和sqlite-jdbc-3.8.7.jar两个jar包, weka.jar可以在weka的安装路径下找到, sqlite-jdbc-3. ...

  6. 启动Android App时,动态将Sqlite数据库文件导入到手机中类方法

    package com.aqioo.db; import java.io.File; import java.io.FileOutputStream; import java.io.InputStre ...

  7. ios创建的sqlite数据库文件如何从ios模拟器中导出

    为了验证数据库的结构,有的时候需要使用一些管理工具来直接查看sqlite数据库的内容,在windows下有sqlite3的专用工具下载,而在ios下也可以使用火狐浏览器的插件sqlitemanager ...

  8. SQL Server 链接服务器连接 SQLite数据库文件

    SQL Server数据库允许通过数据库驱动程序连接各类数据库并进行操作.以下是在SQL Server 2012 R2中建立SQLite的链接服务器. 一.下载SQLite数据库的ODBC驱动程序: ...

  9. Android调用Sqlite数据库时自动生成db-journal文件的原因

    数据库为了更好实现数据的安全性,一半都会有一个Log文件方便数据库出现意外时进行恢复操作等.Sqlite虽然是一个单文件数据库,但麻雀虽小五脏俱全,它也会有相应的安全机制存在 这个journal文件便 ...

随机推荐

  1. 243. Shortest Word Distance

    题目: Given a list of words and two words word1 and word2, return the shortest distance between these ...

  2. Windows下使用Visual Studio 2010编译ffmpeg全过程

    在visual studio 2010中调用ffmpeg http://blog.sina.com.cn/s/blog_4178f4bf01018wqh.html Windows下使用Visual S ...

  3. 02-语言入门-02-ASCII码排序

    题目地址: http://acm.nyist.net/JudgeOnline/problem.php?pid=4    描述 输入三个字符(可以重复)后,按各字符的ASCII码从小到大的顺序输出这三个 ...

  4. Android相对布局(RelativeLayout)

    Android相对布局(RelativeLayout) 备注:这里的视图和元素是等同的概念. RelativeLayout是一个允许子视图相对于其他兄弟视图或是父视图显示的视图组(通过ID指定).每个 ...

  5. js 中 typeof 的使用

    js中的变量是松散类型(即弱类型)的,可以用来保存任何类型的数据. typeof 可以用来检测给定变量的数据类型,可能的返回值: 'undefined' --- 这个值未定义 'boolean' -- ...

  6. HDU 1698 Just a Hook (线段树 成段更新 lazy-tag思想)

    题目链接 题意: n个挂钩,q次询问,每个挂钩可能的值为1 2 3,  初始值为1,每次询问 把从x到Y区间内的值改变为z.求最后的总的值. 分析:用val记录这一个区间的值,val == -1表示这 ...

  7. struct TABLE

    struct TABLE { TABLE() {} /* Remove gcc warning */ TABLE_SHARE *s; handler *file; TABLE *next, *prev ...

  8. bzoj4042

    比较好的树形dp,涉及到树上路径的题目,我们往往考虑对路径分类 当我们考虑以x为根的子树,有这样几类路径 1. 起点终点都在子树内 2. 一个点延伸到子树外 对于要选择另一个点在子树外的路径,要建立在 ...

  9. UVa 12096 The SetStack Computer【STL】

    题意:给出一个空的栈,支持集合的操作,求每次操作后,栈顶集合的元素个数 从紫书给的例子 A={{},{{}}} B={{},{{{}}}} A是栈顶元素,A是一个集合,同时作为一个集合的A,它自身里面 ...

  10. Asp.Net时间戳与时间互转

    /// <summary> /// 时间戳转成时间类型 /// </summary> /// <param name="timeStamp">& ...