——–使用SQLiteOpenHelper的请忽略
1、在res文件夹下创建名为raw文件夹,在raw文件夹下新建一个名为sqliteupgrade.properties的properties文件,文件内容如下。
#数据库升级配置文件
#是否升级
upgrade=true
#需要升级的表名
from=iresult
#临时表名
to=iresult_s
#修改的数据表对应类
class=com.hrhy.cc.db.ReportDB
2、接下来开始写升级类,主要有以下步骤:
- 读取properties文件,通过upgrade属性确认是否有表结构发生变化。
- 将需要升级的表重命名为为临时表名。
- 执行原表的建表sql语句创建一张新表。
- 将修改后的临时表数据插入到新表中。
- 删除临时表。
public class SqliteUpgrade {
private Properties props;
private SQLiteDatabase db;
private Context mContext;
public SqliteUpgrade(Context context){
this.mContext = context;
db = context.openOrCreateDatabase("CubeCare.db", Context.MODE_PRIVATE, null);
props=new Properties();
int id = context.getResources().getIdentifier("sqliteupgrade", "raw", context.getPackageName());
try {
props.load(context.getResources().openRawResource(id));
} catch (Exception e) {
T.showShort(context, "未找到文件");
}
if(isUpgrade()){
upgradeTables();
}
}
/**
* 判断是否需要升级数据表
* @return
*/
private boolean isUpgrade(){
boolean isUpgrade = Boolean.valueOf(props.getProperty("upgrade"));
return isUpgrade;
}
/**
* 升级数据库表
*/
public void upgradeTables(){
db.beginTransaction();
String column = "";
try {
//1、将需要修改的表重命名
String from = props.getProperty("from");//原表名
String to = props.getProperty("to");//修改后的表名
String sql = "ALTER TABLE " + from +" RENAME TO " + to;
//重命名表
db.execSQL(sql);
//2、通过反射调用数据库操作类 创建表
Class<?> cls = Class.forName(props.getProperty("class"));
cls.getConstructor(Context.class,SQLiteDatabase.class).newInstance(mContext,db);
//3、向新表中插入数据
String[] columns = getColumnNames(to);
for (int i = 0; i < columns.length; i++) {
column += columns[i]+",";
}
column=column.substring(0, column.length()-1);
sql = "INSERT INTO " + from +
" (" + column + ") " +
" SELECT " + column + " FROM " + to;
//4、删除修改之前的数据表
db.execSQL("DROP TABLE IF EXISTS " + to);
db.setTransactionSuccessful();
} catch (Exception e) {
L.d(e.getMessage());
}finally{
db.endTransaction();
}
}
/**
* 获取数据库表的列名
* @return
*/
private String[] getColumnNames(String tname){
String[] columnNames = null;
Cursor c = null;
try {
c = db.rawQuery("PRAGMA table_info(" + tname + ")", null);
if (null != c){
int columnIndex = c.getColumnIndex("name");
if (-1 == columnIndex){
return null;
}
int index = 0;
columnNames = new String[c.getCount()];
for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()){
columnNames[index] = c.getString(columnIndex);
index++;
}
}
} catch (Exception e) {
L.d(e.getMessage());
}finally{
if(null!=c){
c.close();
}
}
return columnNames;
}
}
中间使用了java读入Properties文件的类和反射
3、下边是创建表的类的构造方法,需要修改时直接修改建表语句即可,但是升级一定要在使用该表之前,否则可能出现错误。
public ReportDB(Context context,SQLiteDatabase sqldb){
this.context = context;
//创建数据库
if(sqldb==null){
db=context.openOrCreateDatabase("CubeCare.db", Context.MODE_PRIVATE, null);
}else{
db = sqldb;
}
//为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
db.execSQL("create table if not exists iresult "
+ "(tid TEXT, did TEXT,iid TEXT,"
+ "itype TEXT,iresult TEXT,pid TEXT,nid TEXT,passtime TEXT,ctime TEXT,istate TEXT,extena TEXT,extenb TEXT,"
+ "PRIMARY KEY(iid, extena))");
//创建唯一索引
// db.execSQL("create unique index index_tid_extean on reportdate (tid,extena)");
}
之前是不需要在构造方法中传入SQLiteDatabase的,但是升级表结构时打开了SQLiteDatabase,但是在构造方法中再次打开SQLiteDatabase时会报错,所以将升级时打开的SQLiteDatabase当参数传入构造方法。