Android中数据持久化存储可以使用SQLite,常用的是SQLiteOpenHelper。这样就会引申出一些数据库升级的问题。
比如,数据库V1版本中原始表中只有2个字段,在升级数据库V2版本中想要在表中多加1个字段。或者是 用户直接安装的是数据库V2版本,如何保证所有表中的字段是最新的?
假设有数据库V1,数据库V2,数据库V3。存在2种安装情况,都要考虑到。
1,首先安装V1,依次升级V2,V3。
2,首先安装V1,卸载V1之后安装V2,卸载V2,然后安装V3。
SQLiteOpenHelper的onCreate()方法只会在初次创建数据库的时候调用。而onUpgrade()方法会在数据库升级的时候调用。像上述情况V1升级V2则会调用该方法。而若直接安装V2,则只会调用onCreate()方法,并不会调用到onUpgrade()方法,这个时候需要在onCreate()方法中主动调用onUpgrade()方法并在方法内部判断只有当新版本号大于老版本号的时候才执行相应的逻辑。
创建工程DBTest,继承SQLiteOpenHelper.
public class DBSQLiteOpenHelper extends SQLiteOpenHelper {
private static String DBName = "student.db";
private static final int oldVersion = 1;
private static final int currentVersion = 1;
private static final String TAG = "DBSQLiteOpenHelper";
private static DBSQLiteOpenHelper instance = null;
private String tabName = "user";
private DBSQLiteOpenHelper(Context context) {
super(context, DBName, null,currentVersion);
}
public static DBSQLiteOpenHelper getInstance(Context context) {
if (instance == null) {
synchronized (DBSQLiteOpenHelper.class) {
if (instance == null)
instance = new DBSQLiteOpenHelper(context);
}
}
return instance;
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table if not exists "+tabName+" (_id integer primary key autoincrement, name nchar,age nchar)";
db.execSQL(sql);
Log.e(TAG, "onCreate: ");
//首次安装检查是否有更新
onUpgrade(db,oldVersion,currentVersion);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(TAG, "oldVersion: "+oldVersion);
Log.e(TAG, "newVersion: "+newVersion);
if (oldVersion < newVersion){
switch (oldVersion){
case 1:
upgradeToVersionTwo(db);
onUpgrade(db,2,newVersion);
break;
case 2:
upgradeToVersionThree(db);
onUpgrade(db,3,newVersion);
break;
default:
break;
}
}
}
/**
* user表新增1个字段
* @param db
*/
private void upgradeToVersionTwo(SQLiteDatabase db) {
String sql = "alter table "+tabName+" add column gender nchar";
db.execSQL(sql);
Log.e(TAG, "upgradeToVersionTwo: ");
}
/**
* 创建新表
* @param db
*/
private void upgradeToVersionThree(SQLiteDatabase db) {
String tableName = "record";
String sql = "create table if not exists "+tableName+" (_id integer primary key autoincrement, chinese nchar,english nchar)";
db.execSQL(sql);
Log.e(TAG, "upgradeToVersionThree: ");
}
}
在MainActivity中调用创建数据库逻辑。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBSQLiteOpenHelper dbsqLiteOpenHelper = DBSQLiteOpenHelper.getInstance(getApplicationContext());
dbsqLiteOpenHelper.getWritableDatabase();
}
}
当前版本currentVersion为1,即V1(创建user表),修改currentVersion=2,重新编译生成V2(添加字段),再修改currentVersion=3,重新编译生成V3(创建新表record)。如图:
下面我们就可以来测试一下了。
首先安装V1,打开程序,Log如下:
调用了onCreate()方法,由于主动调用了onUpgrade()方法,所以会打印出oldVersion 和 newVersion 。由于判断条件的限定所以不往下继续执行。
使用DDMS查看手机文件,数据库存放在data/data/包名/databases目录下
student.db数据库已被创建,将其导出到桌面使用Navicat Premium 打开查看,user表已被创建。name字段和age字段都创建了。
下面我们将V2版本覆盖安装,打开程序,通过log发现调用了onUpgrade()方法,并调用了upgradeToVersionTwo()方法。
重新导出数据库文件并查看发现 gender 字段已经添加到user表中
然后将V3版本覆盖安装,打开程序,通过log发现调用了onUpgrade()方法,并调用了upgradeToVersionThree()方法。
重新导出数据库文件并查看发现 新表record 已经创建
下面我们再测一下直接安装V2,先将软件卸载,然后安装V2,,log如下
发现程序执行了onCreate()方法,并且执行了upgradeToVersionTwo()方法。为什么会执行到upgradeToVersionTwo()方法呢?这是首次安装,并不会调用数据库升级逻辑的。是因为我们在 onCreate()方法中手动调用了onUpgrade()方法。
重新导出数据库文件并查看,发现user表中gender字段已被添加上。
然后卸载V2,安装V3,log如下
重新导出数据库文件并查看,发现user表中gender字段已被添加。并且 record表也创建了。保证了数据库的统一性。