Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onUpgrade database - oldVersion - newVersion

I am using this DataBaseHelper.class and I am stuck on the onUpgrade()-method. I do not know how to figure out what the version number of the database is. I could set the version to 1, the first time i publish it and when I publish an update I simply could set the version to 2 (myDataBase.setVersion(2);). But it will only be 2 as long as the app is running. The next time it will be started it is 1 again. The same happens to private static int DATABASE_VERSION. I was thinking about storing the version number in an extra table but this does not seem to be best practice in my view.

So how do you make sure that the version number has increased after an upgrade and that it keeps it (the value which was assigned to private static int DATABASE_VERSION or myDataBase.getVersion();)?

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



}
like image 261
BenjaminButton Avatar asked Aug 24 '11 10:08

BenjaminButton


2 Answers

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

Yes, you need this. (Even better, make it final too.)

This tells the database helper what the latest version of the database schema is. This should be fixed in your app code, and incremented whenever you alter the schema.

When your app starts up, the helper does a check at runtime that your code's idea of the latest version is the same as the version which was active when the database was last created or upgraded. (This is what db.getVersion() is for.) If the numbers don't match, then the helper knows that the stored database is out-of-date with respect to your application code, and so it runs the upgrade routine.

It looks as if you're not creating the database from scratch, but importing an existing database from your assets. When you do this initial import, this is the time at which to make sure the stored version matches your code's version; either apply it directly to the database file in your assets, or, if you're sure the database file in your assets matches the code, then you call setVersion(DATABASE_VERSION).

In any case, you shouldn't be trying to modify the version numbers in the onUpgrade() routine. This is only ever called if the versions don't match, and all you're supposed to do here is make whatever changes are needed to bring the database up-to-date. The helper will manage the storing of the new version number once the upgrade is complete.

like image 174
Graham Borland Avatar answered Nov 16 '22 11:11

Graham Borland


Adding some info to Graham Borland answer. I will explain with the scenario of application in which your database is in asset folder and you copy it to to your package folder if its not already present there. Now if you want to upgrade your app with updated database. you need to set

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

in your Database helper class.

(Any integer which should be more than initial db version which you set initialy in this class)

After that you need to add code for override onUpgrade() In this scenarion I overrite old db with latest.You may change your code as your liking

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

If you need any explanation please post in comment :)

like image 26
sandeep_jagtap Avatar answered Nov 16 '22 12:11

sandeep_jagtap