SQLite数据库版本升级的管理实现

简介: 我们知道在SQLiteOpenHelper的构造方法: super(Context context, String name, SQLiteDatabase.

我们知道在SQLiteOpenHelper的构造方法:


super(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

中最后一个参数表示数据库的版本号.当新的版本号大于当前的version时会调用方法:
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

所以我们的重点是在该方法中实现SQLite数据库版本升级的管理


当我们项目刚开始的时候第一版SQLiteOpenHelper是这样写的:

package cc.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
/**
 * Demo描述:
 * SQLite数据库版本升级的管理实现
 * 
 * 参考资料:
 * http://blog.csdn.net/guolin_blog
 * Thank you very much
 */
public class DataBaseOpenHelper extends SQLiteOpenHelper {
    private final static String DATABASE_NAME="test.db";
    private static DataBaseOpenHelper mDataBaseOpenHelper;
    
    public static final String CREATE_PERSON=
    "create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
    
	public DataBaseOpenHelper(Context context,String name,CursorFactory factory,int version) {
		super(context, name, factory, version);
	}

	
	//注意:
	//将DataBaseOpenHelper写成单例的.
	//否则当在一个for循环中频繁调用openHelper.getWritableDatabase()时
	//会报错,提示数据库没有执行关闭操作
	static synchronized DataBaseOpenHelper getDBInstance(Context context) {
		if (mDataBaseOpenHelper == null) {
			mDataBaseOpenHelper = new DataBaseOpenHelper(context,DATABASE_NAME,null,1);
		}
		return mDataBaseOpenHelper;
	} 
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_PERSON);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		
	}

}


在几天之后根据项目需求,需要添加一张student表,于是DataBaseOpenHelper就出现了第二版:

package cc.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseOpenHelper extends SQLiteOpenHelper {
    private final static String DATABASE_NAME="test.db";
    private static DataBaseOpenHelper mDataBaseOpenHelper;
    
    public static final String CREATE_PERSON=
    "create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
    
    public static final String CREATE_STUDENT=
    "create table student(studentid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
    
	public DataBaseOpenHelper(Context context,String name,CursorFactory factory,int version) {
		super(context, name, factory, version);
	}

	
	//注意:
	//将DataBaseOpenHelper写成单例的.
	//否则当在一个for循环中频繁调用openHelper.getWritableDatabase()时
	//会报错,提示数据库没有执行关闭操作
	static synchronized DataBaseOpenHelper getDBInstance(Context context) {
		if (mDataBaseOpenHelper == null) {
			//改动1
			mDataBaseOpenHelper = new DataBaseOpenHelper(context,DATABASE_NAME,null,2);
		}
		return mDataBaseOpenHelper;
	} 
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_PERSON);
		//改动2
		db.execSQL(CREATE_STUDENT);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		//改动3
		switch (oldVersion) {
		
		case 1:
		db.execSQL(CREATE_STUDENT);

		default:
		}
	}

}

较版本一在版本二中有三处修改的地方:

1 版本号变成了2

2 在onCreate()方法中添加了代码db.execSQL(CREATE_STUDENT);创建student表

   因为有的用户根本就没有第一版本的APP,直接从市场下载了第二版本的App。所以当然会执行onCreate()而不会执行onUpgrade()

3 在onUpgrade()做了处理:当oldVersion为1时调用db.execSQL(CREATE_STUDENT);创建student表

   因为有的用户手机上本来就有第一版本的APP,所以在App升级到第二版本时会执行onUpgrade(),不会执行onCreate()

通过这样的处理使得不同的情况下使用第二版APP时都会生成student表



又过了一个月,根据项目变更,需要给person表添加一个字段genderid,于是DataBaseOpenHelper就出现了第三版:

package cc.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseOpenHelper extends SQLiteOpenHelper {
    private final static String DATABASE_NAME="test.db";
    private static DataBaseOpenHelper mDataBaseOpenHelper;
    
    //改动1
    public static final String CREATE_PERSON=
    "create table person(personid integer primary key autoincrement,name varchar(20),phone VARCHAR(12)),genderid integer)";
    
    public static final String ALTER_PERSON="alter table person add column genderid integer";
    
    public static final String CREATE_STUDENT=
    "create table student(studentid integer primary key autoincrement,name varchar(20),phone VARCHAR(12))";
    
	public DataBaseOpenHelper(Context context,String name,CursorFactory factory,int version) {
		super(context, name, factory, version);
	}

	
	//注意:
	//将DataBaseOpenHelper写成单例的.
	//否则当在一个for循环中频繁调用openHelper.getWritableDatabase()时
	//会报错,提示数据库没有执行关闭操作
	static synchronized DataBaseOpenHelper getDBInstance(Context context) {
		if (mDataBaseOpenHelper == null) {
			//改动2
			mDataBaseOpenHelper = new DataBaseOpenHelper(context,DATABASE_NAME,null,3);
		}
		return mDataBaseOpenHelper;
	} 
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_PERSON);
		db.execSQL(CREATE_STUDENT);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		switch (oldVersion) {
		
		case 1:
		db.execSQL(CREATE_STUDENT);
		
		//改动3
		case 2:
	    db.execSQL(ALTER_PERSON);

		default:
		}
	}

}



较版本二在版本三中有三处修改的地方:

1 改变了CREATE_PERSON语句,在改语句中增加了一个字段genderid

   和前面的描述类似,有的用户第一次安装该APP时就直接下载了第三版

2 修改版本号为3

   应对了用户从第一版本或者第二版本升级到第三版本的情况(见下分析)

3 在onUpgrade()方法中)做了处理:当oldVersion为2时调用 db.execSQL(ALTER_PERSON);修改person表,增加genderid字段

   应对了用户从第二版本升级到第三版本的情况(见下分析)


注意一个问题:为什么这里的switch语句在每个case中没有break???

这是为了保证跨版本升级的时候每次数据库的升级都会执行到。

比如从第二版升级到第三版本,那么case 2会被执行。

比如从第一版直接升级到第三版本,那么case 1肯定会被调用,由于没有break所以会穿透switch语句又执行case 2语句继续升级,从而保证了数据的所有版本中的升级都会被执行到。


目录
打赏
0
0
0
0
24
分享
相关文章
客户说|知乎基于阿里云PolarDB,实现最大数据库集群云原生升级
近日,知乎最大的风控业务数据库集群,基于阿里云瑶池数据库完成了云原生技术架构的升级。此次升级不仅显著提升了系统的高可用性和性能上限,还大幅降低了底层资源成本。
高性能云盘:一文解析RDS数据库存储架构升级
性能、成本、弹性,是客户实际使用数据库过程中关注的三个重要方面。RDS业界率先推出的高性能云盘(原通用云盘),是PaaS层和IaaS层的深度融合的技术最佳实践,通过使用不同的存储介质,为客户提供同时满足低成本、低延迟、高持久性的体验。
在C++的QT框架中实现SQLite数据库的连接与操作
以上就是在C++的QT框架中实现SQLite数据库的连接与操作的基本步骤。这些步骤包括创建数据库连接、执行SQL命令、处理查询结果和关闭数据库连接。在实际使用中,你可能需要根据具体的需求来修改这些代码。
216 14
时序数据库 InfluxDB 3.0 版本性能实测报告:写入吞吐量提升效果验证
TSBS 测试表明,对于少于 100 万台设备的数据集,InfluxDB OSS 3.0 的数据写入速度实际上比 InfluxDB OSS 1.8 更慢。 对于 100 万台及以上设备的数据集,InfluxDB OSS 3.0 的数据写入性能才开始超过 InfluxDB OSS 1.8。 InfluxDB OSS 3.0 的数据写入接口与 InfluxDB 1.8 并不兼容,用户无法顺利迁移。
190 7
【YashanDB知识库】数据库升级后用yasboot在线扩充备节点出现报错
本文来自YashanDB官网,讨论从22.2.4.1升级至23.2.2.100过程中遇到的在线扩容问题。使用yasboot增加备节点时出现“no replication addr in node 1-1”错误,尽管数据库中存在相关配置。原因是早期托管功能未支持扩容,导致OM无法获取新库配置。提供两种规避方法:一是手动修改`cod_domor.db`信息并调整配置文件;二是手动安装YashanDB并配置备机。最终已向研发反馈,将在扩容时优化配置检查逻辑。
让数据与AI贴得更近,阿里云瑶池数据库系列产品焕新升级
4月9日阿里云AI势能大会上,阿里云瑶池数据库发布重磅新品及一系列产品能力升级。「推理加速服务」Tair KVCache全新上线,实现KVCache动态分层存储,显著提高内存资源利用率,为大模型推理降本提速。
【上云基础系列04】基于标准架构的数据库升级
本文回顾了业务上云从基础到进阶的理念,涵盖基础版和全栈版架构。在“入门级:上云标准弹性架构基础版”的基础上,本文针对数据库升级,重点介绍了高可用数据库架构的升级方案,确保数据安全和业务连续性。最后,附有详细的“上云标准弹性架构”演进说明,帮助用户选择合适的架构方案。
时序数据库TDengine 3.3.5.0 发布:高并发支持与增量备份功能引领新升级
TDengine 3.3.5.0 版本正式发布,带来多项更新与优化。新特性包括提升 MQTT 稳定性和高并发性能、新增 taosX 增量备份与恢复、支持 JDBC 和 Rust 连接器 STMT2 接口、灵活配置 Grafana Dashboard 等。性能优化涵盖查询内存管控、多级存储迁移、强密码策略等,全面提升时序数据管理的效率和可靠性。欢迎下载体验并提出宝贵意见。
172 5
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
854 15
数据库知识:了解SQLite或其他移动端数据库的使用
【10月更文挑战第22天】本文介绍了SQLite在移动应用开发中的应用,包括其优势、如何在Android中集成SQLite、基本的数据库操作(增删改查)、并发访问和事务处理等。通过示例代码,帮助开发者更好地理解和使用SQLite。此外,还提到了其他移动端数据库的选择。
178 8
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等