2013-04-17 23 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