Android开发涉及到的数据库采用的是轻量级的SQLite3,而在实际开发中,在存储一些简单的数据,使用SharedPreferences就足够了,只有在存储数据结构稍微复杂的时候,才会使用数据库来存储。而数据库表的设计往往不是一开始就非常完美,可能在应用版本开发迭代中,表的结构也需要调整,这时候就涉及到数据库升级的问题了。
数据库升级
数据库升级,主要有以下这几种情况:
增加表
删除表
修改表
增加表字段
删除表字段
增加表和删除表问题不大,因为它们都没有涉及到数据的迁移问题,增加表只是在原来的基础上CRTATE TABLE,而删除表就是对历史数据不需要了,那只要DROP TABLE即可。那么修改表呢?
其实,很多时候,程序员为了图个方便,最简单最暴力的方法就是,将原来的表删除了然后重新创建新的表,这样就不用考虑其他因素了。但这样对于用户来说,体验是非常不好的,比如:用户当前下载列表正在下载文件,此时进行更新,而新版本有个更新点是升级了下载列表的数据库表,那么用户更新完之后发现下载列表变空了,那么用户看到辛辛苦苦下载的99%文件.avi没来,那不崩溃了,这种体验是非常不好的,分分钟就卸载你的应用。
那么数据库表升级时,数据迁移就显得非常重要了,那么如何实现呢?
表升级,数据迁移
现在开发,为了效率,都会使用第三方,本文数据库方面是基于ORMLite的,所以接下来讨论的都是基于此。
1 ->2 ->3
A
A+
A
B
B-
B
C
C
C+
上表的意思是:版本升级从版本号1升级到2再升级到3,1->2->3,期间表ABC的变化,‘+’表示该表增加了字段,‘-’表示该表删除了字段,例如1升级到2,表A增加了字段,表B删除了字段,表C没有发生变化。
首先,我们要先理解SQLiteOpenHelper中
/**
* Called when the database is created for the first time. This is where the
* creation of tables and the initial population of the tables should happen.
*
*@param db The database.
*/
public abstract void onCreate(SQLiteDatabase db);
和
/**
* Called when the database needs to be upgraded. The implementation
* should use this method to drop tables, add tables, or do anything else it
* needs to upgrade to the new schema version.
*@param db The database.
*@param oldVersion The old database version.
*@param newVersion The new database version.
*/
public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);
什么时候调用。文档说得很清楚了,onCreate()是数据库第一次创建的时候调用,而onUpgrade()是当数据库版本升级的时候调用。
首先,先简单的创建A、B、C三个类,并使用OrmLite注解来创建表
A.class
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "tb_a")
public class A {
@DatabaseField(generatedId = true)
public int id;
@DatabaseField
public String name;
}
B.class
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "tb_b")
public class B {
@DatabaseField(generatedId = true)
public int id;
@DatabaseField
public String name;
@DatabaseField
public String age;
}
C.class
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
@DatabaseTable(tableName = "tb_c")
public class C {
@DatabaseFi