GreenDao Schema Update

I saw another question about updating / migrating a schema using green dao ( here )

There are many links in this answer to a good template to use when updating the schema, however there are no examples of what you actually do with the data in order to transfer it correctly, and I had problems finding something.

In my case, my migration is incredibly straightforward - I do not want to convert any existing data, I just need to add some new tables to my schema, which, I suspect, is a fairly common situation.

What is the easiest way to add new tables to your schema without deleting the data that your users already saved? A concrete example would be greatly appreciated.

It would be nice if greenDao provided a class similar to DevOpenHelper, which would simply add new tables / columns that did not previously exist in the schema without first dropping the existing tabs / data.

+24
android orm greendao
Apr 22 '13 at 18:27
source share
3 answers

Finally, I managed to delve into it myself and realized that it is quite easy to add a new table, saving the data in the old tables.

DISCLAIMER . Although I understand that this implementation is specific to my scenario, I think it is useful for someone like me who used the Android ORM tool (greenDao) exclusively to work with SQLite on Android. I understand that this is quite common for those of you who wrote your own table creation queries from the very beginning, but for those who were protected from the courage to use SQLite DB with Android, I think this example will be useful.

ANSWER: You can either modify the inner class DevOpenHelper, or create your own class. I decided to change DevOpenHelper for a while so that my example is simple - however, note that if you restore your greendao classes, DevOpenHelper will be overwritten. It would be better to create your own class, for example "MyOpenHelper", and use it instead.

Prior to my changes, DevOpenHelper.onUpgrade looked like this:

@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); dropAllTables(db, true); onCreate(db); } 

Instead of dropping all tables, take a look at the createAllTables method, which is automatically generated by GreenDao.

Rewrite onUpgrade to check if "oldVersion" is the one you want to upgrade, and then call the createTable methods on the "new" tables. This is what my onUpgrade method looks like:

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + //Going from older schema to new schema if(oldVersion == 3 && newVersion == 4) { boolean ifNotExists = false; //Leave old tables alone and only create ones that didn't exist //in the previous schema NewTable1Dao.createTable(db, ifNotExists); NewTable2Dao.createTable(db, ifNotExists); NewTable3Dao.createTable(db, ifNotExists); NewTable4Dao.createTable(db, ifNotExists); } else { dropAllTables(db, true); onCreate(db); } } 

Adding a new column will be similar, except that you will need to write some SQL or take a look at the automatically generated SQL create statements from greenDao and use them.

To add one new column (NEW_COLUMN, assuming its type is INTEGER) to the existing table (EXISTING_TABLE), do the following:

 db.execSQL("ALTER TABLE 'EXISTING_TABLE' ADD 'NEW_COLUMN' INTEGER"); 

For me right now all I had to do was add new tables so that it turned out to be pretty straightforward. Hope someone finds this helpful.

+39
May 05 '13 at 15:43
source share

I made a slightly different approach for automatically processing updates regardless of where the previous user came from. First I created a class that implements the onUpgrade method in SQLDatabase

 public abstract class AbstractMigratorHelper { public abstract void onUpgrade(SQLiteDatabase db); } 

All migrators helpers, which I will declare later, are inherited from this class.

I will write an example of one of them

 public class DBMigrationHelper5 extends AbstractMigratorHelper { /* Upgrade from DB schema x to schema x+1 */ public void onUpgrade(SQLiteDatabase db) { //Example sql statement db.execSQL("ALTER TABLE user ADD COLUMN USERNAME TEXT"); } } 

After that, you need to implement the logic of the class actually called during the update, where you will need to delete the previous DevOpenHelper for the user one, which may look like

 public static class UpgradeHelper extends OpenHelper { public UpgradeHelper(Context context, String name, CursorFactory factory) { super(context, name, factory); } /** * Here is where the calls to upgrade are executed */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { /* i represent the version where the user is now and the class named with this number implies that is upgrading from i to i++ schema */ for (int i = oldVersion; i < newVersion; i++) { try { /* New instance of the class that migrates from i version to i++ version named DBMigratorHelper{version that the db has on this moment} */ AbstractMigratorHelper migratorHelper = (AbstractMigratorHelper) Class.forName("com.nameofyourpackage.persistence.MigrationHelpers.DBMigrationHelper" + i).newInstance(); if (migratorHelper != null) { /* Upgrade de db */ migratorHelper.onUpgrade(db); } } catch (ClassNotFoundException | ClassCastException | IllegalAccessException | InstantiationException e) { Log.e(TAG, "Could not migrate from schema from schema: " + i + " to " + i++); /* If something fail prevent the DB to be updated to future version if the previous version has not been upgraded successfully */ break; } } } } 

So, if you carefully call your migration assistants (i.e. MigrationHelper5 moves from Schema 5 to Schema 6), you can implement this logic, and then in each MigratorHelper class just implement the execSQL call with all the sql code you need to implement.

Finally, another note, if you are working with proguard, the find name by class method may not work, because the class names change when the code gets messy. You might want to add an exception to the proguard configuration file (proguard-rules.pro) to exclude any class that extends from AbstractMigratorHelper

 # Avoid errors when upgrading database migrators -keep public class * extends yourpackage.locationofyourclass.AbstractMigratorHelper 
+8
Sep 23 '14 at 9:16
source share

I do it a little differently.

I add new @DatabaseTable classes and any @DatabaseFields classes to existing @DatabaseTable classes and run DatabaseConfigUtil.

Then I will add a new method to my DatabaseUpgrader class and change my DatabaseHelper by changing the DATABASE_VERSION value and the onUpdate method

 public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final int DATABASE_VERSION = 3; @Override public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) { if (newVersion > oldVersion) { switch (oldVersion) { case 1: DatabaseUpdater.from1to2(connectionSource); DatabaseUpdater.from2to3(connectionSource); break; case 2: DatabaseUpdater.from2to3(connectionSource); break; default: onCreate(db); } } } public static DatabaseHelper getInstance() { return DatabaseHelper.mHelper; } public static void setInstance(Context context) { DatabaseHelper.mHelper = new DatabaseHelper(context); } … } 

And then in the DatabaseUpdater class

 public class DatabaseUpdater { private static final String TAG = "DatabaseHelper"; public static void from1to2(ConnectionSource connectionSource) { try { DatabaseHelper helper = DatabaseHelper.getInstance(); //Example add a table TableUtils.createTable(connectionSource, AnotherEntity.class); } catch (SQLException e) { Log.e(TAG, "Error upgrading database to v2: ", e); } catch (java.sql.SQLException e) { e.printStackTrace(); } } public static void from2to3(ConnectionSource connectionSource) { try { DatabaseHelper helper = DatabaseHelper.getInstance(); //Example add a field to a table RuntimeExceptionDao<MyEntity, Integer> myDao = helper.getMyDao(); diaryDao.executeRaw("ALTER TABLE myEntity ADD firstNewField"); diaryDao.executeRaw("ALTER TABLE myEntity ADD anotherNewField"); } catch (SQLException e) { Log.e(TAG, "Error upgrading database to v3: ", e); } } } 
+5
Aug 16 '13 at 6:56 on
source share



All Articles