2011-08-24 78 views
7

我正在使用这个DataBaseHelper.class,并卡在onUpgrade() - 方法上。我不知道如何弄清楚数据库的版本号是什么。我可以将版本设置为1,第一次发布它,当我发布更新时,我可以将版本设置为2 (myDataBase.setVersion(2);)。但只要应用程序运行,它只会是2。下次启动时,它又是1。 private static int DATABASE_VERSION也是如此。我正在考虑将版本号存储在额外的表格中,但在我看来,这似乎不是最佳实践。onUpgrade数据库 - oldVersion - newVersion

那么如何确保版本号在升级后增加并保持不变(值分配为private static int DATABASE_VERSIONmyDataBase.getVersion();)?

的DataBaseHelper级:

public class DataBaseHelper extends SQLiteOpenHelper { 

    //The Android's default system path of your application database. 
    private static String DB_PATH = "/data/data/com.mydatabase.db/databases/"; 

    private static String DB_NAME = "database.sl3"; 

    private SQLiteDatabase myDataBase; 

    private final Context myContext; 


    // Do you need this? 
    private static int DATABASE_VERSION = 2; 
    // or is this correct: 
    // private static int DATABASE_VERSION = myDataBase.getVersion(); 


    /** 
    * Constructor 
    * Takes and keeps a reference of the passed context in order to access to 
    * the application assets and resources. 
    * 
    * @param context 
    */ 
    public DataBaseHelper(Context context) { 

     super(context, DB_NAME, null, DATABASE_VERSION); 
     this.myContext = context; 
    } 

    /** 
    * Creates an empty database on the system and rewrites it with your own 
    * database. 
    * */ 
    public void 
     createDataBase() throws IOException { 
     boolean dbExist = checkDataBase(); 

     if (dbExist) { 


     } 
     else { 

      //By calling this method and empty database will be created into the default system path 
      //of your application so we are gonna be able to overwrite that database with our database. 


      this.getWritableDatabase(); 


      try { 

       copyDataBase(); 

      } catch (IOException e) { 

       throw new Error("Error copying database"); 

      } 
     } 

    } 

    /** 
    * 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 
    */ 
    private boolean 
     checkDataBase() { 

     SQLiteDatabase checkDB = null; 

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

     } catch (SQLiteException e) { 

      //database does't exist yet. 

     } 

     if (checkDB != null) { 

      checkDB.close(); 

     } 
     return checkDB != null ? true : false; 
    } 

    /** 
    * Copies your database from your local assets-folder to the just created 
    * empty database in the 
    * system folder, from where it can be accessed and handled. 
    * This is done by transfering bytestream. 
    * */ 
    private void 
     copyDataBase() throws IOException { 

     //Open your local db as the input stream 
     InputStream myInput = myContext.getAssets().open(DB_NAME); 


     // Path to the just created empty db 
     String outFileName = DB_PATH + DB_NAME; 


     //Open the empty db as the output stream 
     OutputStream myOutput = new FileOutputStream(outFileName); 


     //transfer bytes from the inputfile to the outputfile 
     byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = myInput.read(buffer)) > 0) { 
      myOutput.write(buffer, 0, length); 
     } 


     //Close the streams 
     myOutput.flush(); 
     myOutput.close(); 
     myInput.close(); 

    } 

    public void 
     openDataBase() throws SQLException { 

     //Open the database 
     String myPath = DB_PATH + DB_NAME; 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); 



     // Which parameters do I have to pass? 
     onUpgrade(myDataBase, DATABASE_VERSION, 2); 
    } 

    @Override 
    public synchronized void 
     close() { 

     if (myDataBase != null) 
      myDataBase.close(); 

     super.close(); 

    } 

    @Override 
    public void 
     onCreate(SQLiteDatabase db) { 

    } 

    @Override 
    public void 
     onUpgrade( SQLiteDatabase db, 
       int oldVersion, 
       int newVersion) { 

    Log.d ("onUpgrade first log", Integer.toString(myDataBase.getVersion())); 




    if (oldVersion == 1) { 

     // do something 


     // And then do this!? 
     DATABASE_VERSION = 2; 
     // or do this 
     myDataBase.setVersion(2); 
     Log.d ("onUpgrade sedond log", Integer.toString(myDataBase.getVersion())); 

    } 

    else { 
     Log.d("onUpgrade", "else-clause: Already upgraded!"); 
    } 



} 

回答

11
// Do you need this? 
private static int DATABASE_VERSION = 2; 

是的,你需要这个。 (更好的是,也使其成为final。)

这告诉数据库帮助程序数据库模式的最新版本是什么。这应该在您的应用程序代码中修复,并在您更改架构时增加。

当您的应用程序启动时,助手会在运行时检查您的代码对最新版本的想法是否与上次创建或升级数据库时处于活动状态的版本相同。 (这是db.getVersion()的用途。)如果数字不匹配,则助手知道存储的数据库与应用程序代码相比是过时的,因此它运行升级例程。

看起来好像您不是从头开始创建数据库,而是从您的资产中导入现有数据库。当你做这个初始导入时,这是确保存储的版本与你的代码版本相匹配的时间;将其直接应用于资产中的数据库文件,或者如果您确定资产中的数据库文件与代码相匹配,则请致电setVersion(DATABASE_VERSION)

无论如何,您不应该试图修改onUpgrade()例程中的版本号。如果版本不匹配,这种情况只会被调用,并且您应该在此执行的任何操作都需要进行任何更改以使数据库保持最新状态。一旦升级完成,助手将管理新版本号的存储。

+0

嗨格雷厄姆Borland的!你是对的,我从资产文件夹中导入一个现有的数据库,我想这就是我需要的东西,直接把它应用到assets中的数据库文件!但我该怎么做? – BenjaminButton

+0

用_it_表示版本号。 – BenjaminButton

+1

我懂了!在createDataBase类中缺少一行: 'public void createDataBase()throws IOException {boolean dbExist = checkDataBase(); if(dbExist){/ *这行:*/this.getWritableDatabase();} ...' 此外onUpgrade()在创建类DataBaseHelper的新对象时调用**但只有在数据库版本号不匹配。所以这意味着没有必要自己调用升级。如果您发布数据库的更新,只需将版本号增加1,然后在onUpgrade()方法中应用更改。希望能帮助任何人! – BenjaminButton

1

添加一些信息,以格雷厄姆Borland的答案。 我将与应用程序中,你的数据库是在资源文件夹 的情况说明,如果它不存在那里,你把它复制到你的包文件夹。 现在,如果你想用更新的数据库升级你的应用程序。 您需要在您的数据库帮助程序类中设置

private final static int DB_VERSION=2;   // Database Version 

之后,你需要为替代添加代码onUpgrade() 在这种scenarion(其中任何一个应该比你的这个类initialy设置的初始数据库版本以上整数)我overrite旧的数据库与最新的。你可以改变你的代码作为自己的喜好

@Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // TODO Auto-generated method stub 
      CopyNewDatabaseFromAsset(); 
    } 

如果您需要任何解释,请张贴在评论:)

相关问题