j256 / ormlite-android

ORMLite Android functionality used in conjunction with ormlite-core
http://ormlite.com/
ISC License
1.59k stars 366 forks source link

ORMLite Android - Prevent Upgrade inside catch #115

Closed AndrewRogers1994 closed 4 years ago

AndrewRogers1994 commented 4 years ago

I'm trying find a way to prevent the database version from updating in the event that something goes wrong inside the onUpgrade method.

I have the following helper class

public class DatabaseHelper extends OrmLiteSqliteOpenHelper
{
   private DatabaseHelper(Context context)
   {
      super(context, DATABASE_NAME, null, DATABASE_VERSION, R.raw.ormlite_config);
   }

   @Override
   public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion)
   {
       try
       {
         MigrationHelper.RunMigrations(mContext,oldVersion,this);
       }
       catch (Exception e)
       {
            //How can I prevent the version from updating if the migration fails?
       }
    }
}

Prefferably I want to be able to show a message dialog to the user so just throwing an unhandled exception (that would cause the application to crash) isn't really ideal.

Thanks in advance

Edit:

I found a way to do what i needed. I'm not sure if this is the best way to go about it but it accomplishes what I need.

First I created a new interface that looks something like this:

public interface MigrationFailedListener
{
    void onMigrationFailed(String message);
}

And then I modified my DatabaseHelper to look something like this:

public class DatabaseHelper extends OrmLiteSqliteOpenHelper
{
    public static MigrationFailedListener migrationFailedListener;

     @Override
       public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion)
    {
        Log.e("onUpgrade", "oldVersion: " + oldVersion + " newVersion: " + newVersion);
        try
        {
            MigrationHelper.RunMigrations(mContext.get(),oldVersion,this);
        }
        catch (Exception e)
        {
            //Notify the listener that the migration has failed
            if(migrationFailedListener != null)
            {
                migrationFailedListener.onMigrationFailed(e.getMessage());
            }
            //Throwing a RuntimeException appears to be caught by the OrmLiteSqliteOpenHelper and 
            //prevents version increasing (So next to the app is run it will try to upgrade again)
            throw new RuntimeException(e.getMessage());
        }
    }

}

Then I simply set the the migrationFailedListener before any database calls are made like so:

//Set the Migration failed callback
DatabaseHelper.migrationFailedListener = message ->
{
   DatabaseHelper.clearInstance();
   okDialog = new OkDialog(LoginActivity.this, "Database Migration Failed", "There was an issue while migrating database. Application will now close", view ->
    {
      okDialog.cancel();
      finishAndRemoveTask();
     });
    okDialog.show();
};
j256 commented 4 years ago

Can you add some comments to help others @Murded ?

AndrewRogers1994 commented 4 years ago

@j256 I've updated my original post, if you have any suggestions / issues with my solution please let me know