2016-05-05 24 views
1

私のアプリケーションでは、ユーザーはデータをバックアップするために自分のデータベースファイルをエクスポートしてインポートできます。データベースのバージョンを更新し、いくつかの新しい列を追加しました。今すぐユーザーがバージョン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; 
    } 
} 

そして、このdatbaseファイルが有効である場合、私はチェック方法:

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; 
    } 

パブリッククラスDbHelperは{

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

データのエクスポートとインポートの方法について説明できますか?文字通り、データベースファイルを他の保管場所との間でコピーしていますか?あるいは何か他のことをしていますか? – Karakuri

+0

私はapp data/dataからdbファイルを取り出し、ローカルストレージにコピーします。インポートの場合は、既存のファイルを上書きするだけです。 – Anna

答えて

1

SQLiteOpenHelperを拡張文字通りストレージとの間でdbファイルをコピーする場合は、に電話すると理論的にはまたはgetWriteableDatabase()の場合は、データベースのバージョンを確認して、通常のアップグレードフロー(onUpgrade())を呼び出し、古いバージョン番号と新しいバージョン番号の両方を提供する必要があります。そうであれば、onUpgrade()を正しく実装していれば、「うまくいく」べきです。

アップグレードが自動的に行われない場合は、データベースを開いた後でgetVersion()を使用してデータベースのバージョンを確認し、手動でスキーマをアップグレードするコマンドを実行できます。

EDIT

onUpgrade()が自動的に実行するためには、あなたのDbHelperクラスを使用してデータベースを開く必要があります。それがなければ、DbHelperというインスタンスが必要です。そのため、onUpgrade()メソッドを呼び出して、手動で開いたSQLiteDatabaseを渡すことができます。

SQLiteDatabase sqlDb = ...; 
DbHelper dbHelper = ...; 
dbHelper.onUpgrade(sqlDb, sqlDb.getVersion(), DbContract.VERSION); 

DBファイルが有効かどうかを確認する方法は特にありません。契約のすべてのスキーマバージョンを把握し、それぞれを確認する必要があります。扱いにくいようです。代わりに、ファイルをアプリケーションのデータベースディレクトリの一時ファイルにコピーする場合は、DbHelper(オープンしようとする)でファイルを開き、何かが失敗した場合はファイルを中止して削除できますか?成功した場合は、ファイルの名前を変更してデータベースを再度開くだけです。それはおそらく私がそれにアプローチする方法です。

+0

上記を参照してください。私は私の質問を更新します...あなたは私を助けて、私がどこでどのようにonUpgradeを呼び出す必要があるかを教えてください。 – Anna

+0

@Anna私の編集を参照 – Karakuri

+0

ありがとうございました。いくつかのサンプルコードを表示できますか? – Anna

関連する問題