2013-04-17 21 views
0

你可以在下面看到我的數據庫幫助類。我使用預先填充的資產文件夾中導入的sqlite數據庫。每當我將表添加到現有數據庫時,如果我的應用程序已安裝在手機上,則不會出現此類表錯誤。我想我的onUpgrade()方法現在非常好。它的工作原理,不要誤解我的意思,當我將某些數據更改爲現有表時,我會增加db版本並將其更新。但是,如果我添加一個表,我會得到錯誤。我的onUpgrade()方法應該如何?

public class DataBaseHelper extends SQLiteOpenHelper 
{ 
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window 
//destination path (location) of our database on device 
private static String DB_PATH = "/data/data/rs.androidaplikacije.themostcompleteiqtest/databases/"; 
private static String DB_NAME ="pitanja.sqlite";// Database name 
private static SQLiteDatabase mDataBase; 
private final Context mContext; 
private static final int DATABASE_VERSION = 3; 

public DataBaseHelper(Context mojContext) 
{ 
    super(mojContext, DB_NAME, null, 3);// 1 it's Database Version 
    DB_PATH = mojContext.getApplicationInfo().dataDir + "/databases/"; 
    this.mContext = mojContext; 
} 

public void createDataBase() throws IOException 
{ 
    //If database not exists copy it from the assets 


     this.getReadableDatabase(); 
     this.close(); 
     try 
     { 
      //Copy the database from assests 
      copyDataBase(); 
      Log.e(TAG, "createDatabase database created"); 
     } 
     catch (IOException mIOException) 
     { 
      throw new Error("ErrorCopyingDataBase"); 
     } 
    } 

/** 
* Check if the database already exist to avoid re-copying the file each time you open the application. 
* @return true if it exists, false if it doesn't 
*/ 
public boolean checkDataBase(){ 

SQLiteDatabase checkDB = null; 

try{ 
String myPath = DB_PATH + DB_NAME; 
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

}catch(SQLiteException e){ 

//database does't exist yet. 

} 

if(checkDB != null){ 

checkDB.close(); 

} 

return checkDB != null ? true : false; 
} 
    /*Check that the database exists here: /data/data/your package/databases/Da Name 
    private boolean checkDataBase() 
    { 
     File dbFile = new File(DB_PATH + DB_NAME); 
     //Log.v("dbFile", dbFile + " "+ dbFile.exists()); 
     return dbFile.exists(); 
    } 
    */ 

    //Copy the database from assets 
    private void copyDataBase() throws IOException 
    { 
     InputStream mInput = mContext.getAssets().open(DB_NAME); 
     String outFileName = DB_PATH + DB_NAME; 
     OutputStream mOutput = new FileOutputStream(outFileName); 
     byte[] mBuffer = new byte[1024]; 
     int mLength; 
     while ((mLength = mInput.read(mBuffer))>0) 
     { 
      mOutput.write(mBuffer, 0, mLength); 
     } 
     mOutput.flush(); 
     mOutput.close(); 
     mInput.close(); 
    } 

    //Open the database, so we can query it 
    public boolean openDataBase() throws SQLException 
    { 
     String mPath = DB_PATH + DB_NAME; 
     //Log.v("mPath", mPath); 
     mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY); 
     //mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
     return mDataBase != null; 
    } 
    @Override 
    public void close() 
    { 
     if(mDataBase != null) 
      mDataBase.close(); 
     super.close(); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase arg0) { 
     } 

    @Override 
    public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { 
     try { 
      // delete existing? 

      // Copy the db from assests 
      copyDataBase(); 
      Log.e(TAG, "database updated"); 
     } catch (IOException mIOException) { 
      Log.e(TAG, mIOException.toString()); 
      try { 
       throw mIOException; 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

回答

1

有2種方法可以升級,具體取決於您的應用程序。

1)刪除所有舊錶,然後運行onCreate。這基本上抹去了所有的舊數據並重新開始。它是一種很好的技術,如果你可以以某種方式重新生成舊數據,或者不關心它。

2)仔細維護每個發佈版本之間的模式差異,並編寫SQL語句以在它們之間進行適當的更改 - 添加新表,更改現有表以添加/刪除列等。這非常耗時且脆弱的,所以只有當你需要保持這些版本之間的數據時才使用它。

+0

那麼,如何做第一件事?我應該從onUpgrade刪除所有的代碼嗎?它是否很好? – marjanbaz

+0

所以你是從資產目錄複製它。這基本上是我的路徑#1,但從一個預定義的數據庫開始。這個想法很有道理,我沒有在代碼中看到明顯的缺陷。你得到了什麼確切的錯誤?當你說添加一個表時 - 你是否將它添加到資產文件中的數據庫,或者只是在代碼中?因爲如果它只是代碼,你可能會在創建之前嘗試讀取/寫入該表,這顯然是一個錯誤。如果你用這種方式做事情,最好在資產文件中的db中創建每個表。 –

+0

[你可以在這裏看到錯誤](http://stackoverflow.com/questions/16067152/no-such-table-error-whenever-i-add-some-table-to-my-db)。我通過SQLite Manager Firefox插件將表添加到資產文件中的數據庫。 – marjanbaz