在我的应用程序中,用户可以导出和导入他的数据库文件以备份数据。我更新了数据库版本并添加了一些新的列。现在,探测用户备份版本1的旧数据库。 在他试图导入之后,他会得到类似“(1)没有这样的专栏:(这里的专栏名称)”。 如何导入后在旧数据库上调用onUpgrade? 我可以手动调用加载的数据库上的onUpgrade吗? 我怎么解决呢? 在更新应用程序后,我是否需要告诉用户再次进行新备份以确保安全? 任何人都不知道吗?
代码如何导入:
// importing database
public boolean importDB(String path , File dbFile) {
try {
boolean isValid = checkDbIsValid(dbFile);
if(!isValid){
Toast.makeText(context, context.getResources().getString(R.string.errorFile),Toast.LENGTH_LONG).show();
return false;
}
//Last loaded file name will be the auto backup file destination
int lastIndexOf = path.lastIndexOf('/');
String loadedFileName = path.substring(lastIndexOf + 1);
new MySharedPreferences(context).putStringLastFileNameSent(loadedFileName);
FileInputStream fis = new FileInputStream(path);
//Destination to:
String outFileName = DATABASE_DIRECTORY + DbContract.DB_NAME;
OutputStream output = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = fis.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
// Close the streams
output.flush();
output.close();
fis.close();
Toast.makeText(context, context.getResources().getString(R.string.importDatabaseSucceed),Toast.LENGTH_LONG).show();
return true;
} catch (Exception e) {
Toast.makeText(context,context.getResources().getString(R.string.errorImportDatabase),Toast.LENGTH_LONG).show();
e.printStackTrace();
return false;
}
}
这是我如何检查数据库文件是否有效:
public static boolean checkDbIsValid(File db) {
SQLiteDatabase sqlDb;
Cursor cursor;
try {
sqlDb = SQLiteDatabase.openDatabase (db.getPath(), null, SQLiteDatabase.CONFLICT_NONE);
cursor = sqlDb.query(true,DbContract.TABLE_DAY, null, null, null, null, null, null, null);
for( String s : DbContract.ALL_COLUMN_KEYS_IN_TABLE_DAY){
cursor.getColumnIndexOrThrow(s);
}
//This make sure the user can import old database on new Version of table
try {
cursor = sqlDb.query(true,DbContract.TABLE_SETTING,null, null, null, null, null, null, null);
for( String s : DbContract.ALL_COLUMN_KEYS_IN_TABLE_SETTING_v2){
cursor.getColumnIndexOrThrow(s);
}
System.out.println("DATABASE LOADED FROM V2");
}catch (Exception fileNotV1){
System.out.println("ERROR FILE .. IS NOT V2");
try {
for( String s : DbContract.ALL_COLUMN_KEYS_IN_TABLE_SETTING_v1){
cursor.getColumnIndexOrThrow(s);
}
System.out.println("DATABASE LOADED FROM V1");
}catch (Exception fileNotV2){
System.out.println("ERROR FILE .. IS NOT V1");
return false;
}
}
if(DbContract.VERSION<sqlDb.getVersion() ){
return false;
}
sqlDb.close();
cursor.close();
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
} catch (SQLiteException e) {
e.printStackTrace();
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public class DbHelper扩展了SQLiteOpenHelper {
public DbHelper(Context context) {
super(context, DbContract.DB_NAME, null, DbContract.VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DbContract.CREATE_TABLE_WORKS);
db.execSQL(DbContract.CREATE_TABLE_SETTING);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion == 1) {
updateToVersion2(db);
}
}
public void updateToVersion2(SQLiteDatabase db){
db.execSQL("ALTER TABLE " + DbContract.TABLE_SETTING + " ADD "
+ DbContract.COLUMN1 + " REAL DEFAULT 1");
db.execSQL("ALTER TABLE " + DbContract.TABLE_SETTING + " ADD "
+ DbContract.COLUMN0 + " REAL DEFAULT 0");
db.execSQL("ALTER TABLE " + DbContract.TABLE_SETTING + " ADD "
+ DbContract.COLUMN2 + " REAL DEFAULT 0");
}
}
答案 0 :(得分:1)
如果你真的要将db文件复制到存储器中,那么理论上当你调用getReadableDatabase()
或getWriteableDatabase()
时,它应该检查数据库版本并完成典型的升级流程, onUpgrade()
并为您提供旧版和新版本号。如果是这种情况,并且如果您正确实施onUpgrade()
,那么事情应该&#34;只是工作&#34;。
如果升级没有自动进行,打开数据库后,您可以使用getVersion()
自行检查数据库版本,并执行您喜欢的任何命令来手动升级架构。
修改强>
为了让onUpgrade()
自动运行,您需要使用DbHelper
类打开数据库。如果没有,您需要DbHelper
的实例,以便您可以调用其onUpgrade()
方法并将其传递给您手动打开的SQLiteDatabase
。
SQLiteDatabase sqlDb = ...;
DbHelper dbHelper = ...;
dbHelper.onUpgrade(sqlDb, sqlDb.getVersion(), DbContract.VERSION);
我并不特别喜欢检查数据库文件是否有效的方法。您必须跟踪合同中的每个模式版本并检查每个模式;这似乎很笨拙。如果您将文件复制到应用程序数据库目录中的临时文件中,请使用DbHelper
打开它(应该尝试打开它),如果有任何失败,您可以中止并删除文件?如果成功,您只需重命名该文件并重新打开数据库即可。这可能是我接近它的方式。