`
Lagunarock
  • 浏览: 20149 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

Android客户端SQLite数据库升级方案

阅读更多

一,前言

没有采用Android自身提供的那一套数据库操作方式。而是想对SQLite数据库文件有更全面的控制,包括随时导出数据库文件修改表结构,增删数据等等。这样一来虽然在开放中得到不少便利,但是也带来了数据库升级的一些问题。

后来不得已采用了一种方案,可以解决问题,现将方案的全部实现细节记录下来。最后也会提出一些我认为有问题的地方。

 

二,数据库文件拷贝

程序不负责数据库的创建,SQLite数据库文件是在外部创建好的。程序启动阶段拷贝进SD卡。以达到对数据库结构的全面控制。

数据库文件存放位置见附件图片。

public void copyDBFile() {
		// 数据库路径
		if (!FileOperator.checkFile(SysConst.DB_PATH)) {
			boolean result = FileOperator.write2Sdcard(activity,
					R.raw.scpip_collection, SysConst.DB_PATH);
			Debug.log("无数据库文件,首次拷贝" + result);
			if (!result) {
				throw new IllegalAccessError(activity
						.getString(R.string.copy_db_exception));
			} else {
				// 拷贝成功,更新数据库版本
				try {
					PackageInfo info = activity.getPackageManager()
							.getPackageInfo(activity.getPackageName(), 0);
					// 当前程序版本号,在AndroidManifest.xml中定义
					int versionCode = info.versionCode;
					Config.saveDbVer(versionCode);
					Debug.log("拷贝成功" + result);
				} catch (NameNotFoundException e) {
					Debug.e(e);
				}
			}
		} else {
			// 数据库已存在的情况
			if (dbUpdate.needUpdate() ) {
				activity.showProgress("数据库升级中,请稍后", false);
				new Thread() {
					@Override
					public void run() {
						try {
							Debug.log("update db");
							dbUpdate.updateDb();
							handler.sendEmptyMessage(0);
						} catch (Exception e) {
							Debug.e(e);
							handler.sendEmptyMessage(-1);
						}
					};
				}.start();
			}
		}
	}

 其中有几个要点:

1、检测数据库文件是否已经存在。不存在则从raw文件夹复制数据库文件拷贝至SD卡中指定目录。

2、数据库版本是根据应用的versionCode相同。拷贝数据库后,会把当前versionCode写入数据库的表中。

<manifest 
	xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.xxx" 
	android:versionCode="2"
	android:versionName="1.01.001">
	<uses-sdk android:minSdkVersion="8" />

 versionCode在AndroidManifest.xml文件中。

在这种方案下,实际上是由versionCode控制数据库版本,versionName控制程序版本。

3、SD卡指定目录已经存在数据库文件的情况,则读取其中保存的数据库版本号,与versionCode对比,从而确定是否需要升级数据库。代码如下:

public boolean needUpdate() {
		int currVer = Config.getDbVer();
		return currVer < getAppVersion();
	}
	
	public int getAppVersion(){
		try {
			PackageInfo info = context.getPackageManager().getPackageInfo(
					context.getPackageName(), 0);
			// 当前程序版本号,在AndroidManifest.xml中定义
			return info.versionCode;
		} catch (NameNotFoundException e) {
			Debug.e(e);
			return 1;
		}
	}

 

三,升级数据库

包括三个步骤:

1、从程序中拷贝新数据库文件至SD卡指定目录,命名为temp.db。

		String temp = SysConst.DB_FOLDER + "temp.db";
		boolean s1 = FileOperator.write2Sdcard(context, R.raw.scpip_collection,temp);

 

2、分别获取两个数据源。

			//原数据库文件
			BaseDao sd = new BaseDao();
			//新数据库文件
			BaseDao nd = new BaseDao(temp);

 对于SQLite数据库来讲,数据源就是数据库文件。BaseDao是自己封装的,关键在于要可以配置不同的数据源

具体实现的相关代码如下:

	private String dbPath;
	
	public BaseDao() {}
	
	public BaseDao(String dbPath) {
		this.dbPath = dbPath;
	}

public SQLiteDatabase getDb() {
		return SQLiteDatabase.openDatabase(SysConst.DB_PATH, null,
				SQLiteDatabase.OPEN_READWRITE);
	}
	
	public SQLiteDatabase getDb(String dbPath) {
		return SQLiteDatabase.openDatabase(dbPath, null,
				SQLiteDatabase.OPEN_READWRITE);
	}

 

这样就可以根据文件,获取不同的SQLiteDatabase 对象。

 

3、传输数据

把原数据库中的数据查询出来,插入到新数据库中。

	public <E>void transfer(BaseDao sd,BaseDao nd,Class<E> cls) throws Exception{
		List<E> list = sd.find(cls, null);
		nd.batchInsert(list);
	}

 

这里有两个要点,

第一,使用了自行封装的ORM。

第二,使用了SQLite批量插入,增加写入效率。代码如下:

@Override
	public <T> void batchInsert(List<T> datas) throws Exception {
		SQLiteDatabase dba = null;
		if(dbPath == null){
			dba = getDb();
		} else {
			dba = getDb(dbPath);
		}
		int size = datas.size();
		try {
			dba.beginTransaction();
			for (int i = 0; i < size; i++) {
				DaoHelper helper = new DaoHelper(datas.get(i));
				String tableName = helper.getTableName();
				String sql = "select 1 from " + tableName + " where "
						+ helper.getPkCol() + "=";
				Object id = helper.getPkValue();
				if (id instanceof String) {
					sql = sql + "'" + id + "'";
				} else {
					sql = sql + id;
				}
				c = dba.rawQuery(sql, null);
				if (c != null ? (c.getCount() == 1) : false) {
					c.close();
					continue;
				}
				if(c != null){
					c.close();
				}
//				SqlArgs sa = helper.prepareInsert();
//				dba.execSQL(sa.getSql(), sa.getArgs());
				dba.insert(helper.getTableName(), "", helper.getInsertContent());
			}
			dba.setTransactionSuccessful();
			dba.endTransaction();
		} finally {
			dba.close();
		}
	}

 

4、写入当前数据库版本,即从程序获得的versionCode。

5、删除原数据库文件,重命名temp.db。

完整过程如下:

public void updateDb() throws Exception {
		//1,写入新的数据库文件,命名为temp
		String temp = SysConst.DB_FOLDER + "temp.db";
		boolean s1 = FileOperator.write2Sdcard(context, R.raw.scpip_collection,temp);
		Debug.log("s1:" + s1);
		if(s1) {
			//原数据库文件
			BaseDao sd = new BaseDao();
			//新数据库文件
			BaseDao nd = new BaseDao(temp);
			//转移数据
			//此处代码略	
			//删除原数据库文件,重命名临时数据库文件
			if(FileOperator.delSdcardFile(SysConst.DB_PATH)){
				File file = new File(temp);
				file.renameTo(new File(SysConst.DB_PATH));
							}
					//此时更新数据库版本
			Config.saveDbVer(getAppVersion());
		}
	}

 至此,整个数据库升级完成。在保留原数据的基础上,获取了新的数据库结构。

 

四,问题

1,需要保留的原数据与新表结构不符。这个可以在程序中控制,创建新的OR映射。

2,效率问题,如果需要保留的数据量非常大的情况下,是否会出现问题。这个是亟待解决的,目前我还没有想到解决办法。

 

五,总结

这个方案针对的情况是外部创建数据库文件,程序启动时从apk包将数据库文件拷贝进SD卡,从而达到对数据库文件的完全控制。

方案步骤:

1,检测是否需要升级数据库文件。数据库文件版本是由versionCode控制。程序升级时,如果需要升级数据库,则要将versionCode+1。

2,将新数据库文件(存在于apk中),写入SD卡。

3,转移数据。

4,删除原数据库文件,重命名新数据库文件。

5,向新数据库写入当前数据库版本。

  • 大小: 13.7 KB
分享到:
评论
2 楼 yanyuetian 2014-08-01  
说得不错,这里有满足基本升级要求简单的方法:http://www.pedant.cn/2014/08/01/sqliteopenhelper-onupgrade-ondowngrade-handle/ , Anroid SQLite数据库升级,历史数据保留,降级遇到的问题
1 楼 lvsucceed 2014-01-18  
楼主 能不能给发个源码学习学习下啊?
275075066@qq.com  谢谢了

相关推荐

    android sqlite数据库客户端及查看器

    在Android应用开发中,通常会通过SQLiteOpenHelper类来创建、升级和访问SQLite数据库。这个类提供了`getWritableDatabase()`和`getReadableDatabase()`方法来获取数据库对象,并且可以通过`onCreate()`和`onUpgrade...

    基于Android平台的SQLite数据库加密研究.pdf

    "基于Android平台的SQLite...5. SQLite数据库加密的重要性:SQLite数据库加密是Android平台的主要安全issue之一,本文研究了基于Android平台的SQLite数据库加密问题,并提出了一个优化的AES-128算法整库加密方案。

    Android-在浏览器管理中Sqlite数据库

    这个项目可能包含了一个Web服务器和客户端库,允许Android应用通过HTTP接口与Web服务器通信,从而在Web端查看和操作SQLite数据库。使用这类工具时,需要理解其工作原理和API,以便在Android应用中正确集成。 在实际...

    SQLite数据库 ,实现本地、登录、注册、 修改、注销账号、记住密码

    SQLite数据库是一种轻量级的关系型数据库管理系统,常用于移动设备和嵌入式系统中的本地数据存储,因为它无需单独的服务器进程,而是直接在应用程序中运行。在这个场景中,SQLite被用来实现用户账户管理,包括登录、...

    基于Android平台SQLite数据库技术在图书馆中的应用.docx

    通过继承此类,可以轻松地创建、升级和管理SQLite数据库。 2. **SQLiteDatabase类**:此接口提供了一系列用于执行SQL语句的方法,如insert()、delete()、update()和query()等。 3. **ContentProvider**:Android提供...

    基于android的多媒体播放器(服务端+客户端+数据库).zip

    2. **SQLite数据库**:"videoplaydb.sql"文件是SQLite数据库的脚本,用于创建和初始化多媒体播放器所需的数据库结构。在Android中,SQLite是默认的轻量级数据库,常用于存储应用数据,如媒体文件的元信息。 3. **...

    基于Android平台SQLite数据库技术在图书馆中的应用.pdf

    为了实现与SQLite数据库的交互,Android提供了SQLiteOpenHelper类,它提供了一套创建、升级和打开数据库的接口。开发者需要继承这个类并重写相关方法,如onCreate()用于初始化数据库结构,onUpgrade()则用于数据库...

    android sqlite数据库实例

    在实际应用中,Android开发者通常会使用SQLiteOpenHelper这个辅助类来操作SQLite数据库。SQLiteOpenHelper的主要职责是: 1. **创建和升级数据库**:通过`onCreate()`方法创建新的数据库,`onUpgrade()`方法升级已有...

    Delphi XE7 Android平台与PC端同步SQLite 数据库

    本文将详细讨论如何使用Delphi XE7在Android平台上与PC端同步SQLite数据库,以便实现数据的一致性和实时更新。 Delphi XE7是Embarcadero公司推出的一款强大的集成开发环境(IDE),支持Windows、iOS、Android等多个...

    Android平台下通用SQLite数据库模型的设计与实现.pdf

    Android 平台下通用 SQLite 数据库模型的设计与实现 Android 平台下通用 SQLite 数据库模型的设计与实现是指在 Android 平台下设计和实现一个通用的 SQLite 数据库模型。该模型的设计目标是为了降低数据库管理的...

    安卓SQLite数据库相关-基于android平台通过JDBC连接MySQL数据库实现增删查改操作.rar

    在Android平台上,SQLite数据库是默认的轻量级数据库系统,用于存储应用的本地数据。它非常适合小型数据库和离线应用场景,因为它的体积小、效率高且易于使用。然而,有时开发者可能需要在Android应用中与远程MySQL...

    Android和SQLite简介(对官方文档的翻译).doc

    - **全面支持**:Android原生支持SQLite数据库,这意味着开发者可以轻松地在自己的应用程序中集成SQLite数据库。 - **访问控制**:在Android中创建的SQLite数据库只能被同一应用程序内的类访问,从而确保了数据的...

    基于android的智能订餐系统(服务端+客户端+数据库).zip

    本系统集成了服务端、客户端以及数据库,旨在提供便捷的订餐体验,适用于毕业设计、课程设计等项目实践,有助于学习者提升Android应用开发能力。以下将详细解析该系统的组成部分及其关键技术。 首先,我们关注的是...

    Android SQLite数据库开发教学案例设计.pdf

    在Android应用开发中,SQLite数据库是一个重要的组成部分,它为应用程序提供了本地数据存储功能。SQLite是一个轻量级的关系型数据库管理系统,适用于嵌入式系统,如移动设备。在Android平台上,SQLite是默认的数据库...

    android_blog.zip_Android 数据库_Android数据库_android_mysql客户端_服务器 数据库

    "KDWB"可能是项目的核心业务逻辑或者服务器数据库的简称,而"KDWB_Android"则可能代表Android客户端的部分,包含了与服务器通信和本地SQLite数据库操作的相关代码。 6. **数据同步策略**: 在客户端与服务器之间进行...

    Android系统中SQLite数据库使用效率研究.pdf

    在Android应用开发中,SQLite数据库是一个关键的组件,它提供了本地数据存储的功能,适用于轻量级数据管理。本文将深入探讨如何在Android系统中高效地使用SQLite数据库,以提升应用程序的性能和用户体验。 首先,...

    Android移动选课系统 客户端+数据库

    例如,使用ListView或RecyclerView展示课程列表,使用SQLite数据库存储用户信息,以及使用HttpURLConnection或OkHttp进行服务器通信。此外,对于用户体验的优化,如加载优化、触摸反馈、错误处理等也是客户端开发的...

    Android系统中SQLite数据库的研究.pdf

    在Android应用开发中,SQLite数据库是一个关键组成部分,用于存储和管理应用程序的数据。SQLite是一个轻量级、嵌入式的关系型数据库,特别适合于资源...理解并熟练运用这些知识点是进行Android客户端应用开发的基础。

Global site tag (gtag.js) - Google Analytics