【问题标题】:onUpgrade database - oldVersion - newVersiononUpgrade 数据库 - o​​ldVersion - newVersion
【发布时间】:2013-04-03 16:10:50
【问题描述】:

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

那么如何确保版本号在升级后增加并保持不变(分配给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!");
    }



}

【问题讨论】:

    标签: java android sqlite upgrade


    【解决方案1】:
    // Do you need this?
    private static int DATABASE_VERSION = 2;
    

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

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

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

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

    无论如何,您都不应该尝试修改onUpgrade() 例程中的版本号。仅当版本不匹配时才会调用此方法,并且您在这里要做的就是进行所需的任何更改以使数据库保持最新状态。升级完成后,助手将管理新版本号的存储。

    【讨论】:

    • 嗨,格雷厄姆·博兰德!没错,我从资产文件夹中导入了现有数据库,我认为这就是我需要的将其直接应用于资产中的数据库文件!但是我该怎么做呢?
    • it 我指的是版本号。
    • 我成功了!在 createDataBase-class 中缺少一行:public void createDataBase() throws IOException { boolean dbExist = checkDataBase(); if (dbExist) { /* This line: */ this.getWritableDatabase();}... 此外,当创建 DataBaseHelper 类的新对象时调用 onUpgrade()仅当数据库版本号不匹配时。所以这意味着不需要“自己”调用 onUpgrade 。如果您发布数据库的更新,只需将版本 nr 增加 1 并在 onUpgrade() 方法中应用更改。希望对任何人都有帮助!
    • @BenjaminButton 非常感谢您的上述评论已经解决了我的问题。再次非常感谢。
    【解决方案2】:

    向 Graham Borland 答案添加一些信息。 我将解释您的数据库在资产文件夹中的应用程序场景 如果它尚未存在,则将其复制到您的包文件夹中。 现在,如果您想使用更新的数据库升级您的应用程序。 你需要设置

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

    在您的数据库助手类中。

    (任何大于您在此类中设置的初始数据库版本的整数)

    之后,您需要添加覆盖 onUpgrade() 的代码 在这种情况下,我用最新的覆盖旧数据库。您可以根据自己的喜好更改代码

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

    如果您需要任何解释,请在评论中发表:)

    【讨论】:

      猜你喜欢
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 2012-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-17
      相关资源
      最近更新 更多