如何将旧版本的数据库文件导入新版本?

时间:2016-05-05 02:46:35

标签: android database android-sqlite

在我的应用程序中,用户可以导出和导入他的数据库文件以备份数据。我更新了数据库版本并添加了一些新的列。现在,探测用户备份版本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");
    }
  }

1 个答案:

答案 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打开它(应该尝试打开它),如果有任何失败,您可以中止并删除文件?如果成功,您只需重命名该文件并重新打开数据库即可。这可能是我接近它的方式。