onUpgrade数据库 - oldVersion - newVersion

时间:2011-08-24 10:23:23

标签: java android sqlite upgrade

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

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

DataBaseHelper-class:

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!");
    }



}

2 个答案:

答案 0 :(得分:11)

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

是的,你需要这个。 (更好的是,也可以final。)

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

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

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

在任何情况下,您都不应该尝试修改onUpgrade()例程中的版本号。只有在版本不匹配时才会调用此方法,而您在此处应该做的就是进行任何更改以使数据库保持最新状态。升级完成后,帮助程序将管理新版本号的存储。

答案 1 :(得分:1)

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

 private final static int DB_VERSION=2;          // Database Version
数据库帮助程序类中的

(任何应该超过您在此类中初始设置的初始db版本的整数)

之后你需要添加覆盖onUpgrade()的代码 在这个场景中,我用最新的方法覆盖了旧的数据库。您可以根据自己的喜好更改代码

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

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