greenDao架构升级

我看过另一个关于使用green dao进行模式升级/迁移的问题( 这里 )

在该答案中有许多链接可用于在进行模式升级时使用的良好模式 – 但是没有关于您实际对数据执行的操作的示例,以便正确地迁移它并且我无法find任何内容。

就我而言,我的迁移非常直接 – 我不希望转换任何现有数据,我只需要在我的模式中添加一些新表,我怀疑这是一种相当常见的情况。

在不删除用户已保存的数据的情况下,将新表添加到架构的最简单方法是什么? 非常感谢一个具体的例子。

如果greenDao提供了一个类似于DevOpenHelper的类,它将简单地添加先前不存在于模式中的新表/列而不首先丢弃现有的tabes / data,这将是非常棒的。

Solutions Collecting From Web of "greenDao架构升级"

我终于有时间自己深入研究并意识到在保留旧表中的数据的同时添加新表非常容易。

免责声明 :虽然我意识到这个实现特定于我的场景,但我认为对于像我这样使用Android ORM工具(greenDao)专门处理Android上的SQLite的人来说很有帮助。 我理解这对于那些从头开始编写自己的表创建查询的人来说非常普遍,但是对于那些已经避免使用带有Android的SQLite数据库的人来说,我认为这个例子会有所帮助。

解答:您可以修改DevOpenHelper内部类或创建自己的类。 我选择编辑DevOpenHelper暂时保持我的示例简单 – 但是,请注意,如果重新生成greendao类,DevOpenHelper将被覆盖。 最好是创建自己的类,如“MyOpenHelper”,然后使用它。

在我的更改之前,DevOpenHelper.onUpgrade看起来像这样:

@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); } 

不要删除所有表,而是查看GreenDao自动生成的createAllTables方法。

重写onUpgrade以检查“oldVersion”是否是您要升级的那个,然后只调用“new”表的createTable方法。 这是我的onUpgrade方法现在的样子:

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

添加新列将类似,除了您必须编写一些SQL或查看来自greenDao的自动生成的SQL create语句并利用它们。

要向现有表(EXISTING_TABLE)添加单个新列(NEW_COLUMN,假设它是INTEGERtypes),请执行以下操作:

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

对我来说,我需要做的就是添加新的表格,这样才能更加直接。 希望其他人认为这很有用。

无论以前的用户来自哪里,我都会自动处理更新。 首先,我创建了一个在SQLDatabase上实现onUpgrade方法的Class

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

从这个类inheritance我之后将声明的所有迁移器助手

我会写一个例子

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

在此之后,您需要在升级时实际调用的类上实现逻辑,在那里您需要删除以前的DevOpenHelper,以获得可能看起来像这样的自定义的DevOpenHelper

 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; } } } } 

因此,如果您仔细命名您的Migration Helpers(即MigrationHelper5从架构5迁移到架构6),您可以实现此逻辑,然后在每个MigratorHelper类中,只需使用您需要实现的所有sql代码实现execSQL调用。

最后再说一句,如果你正在使用proguard,那么按类查找名称的方法可能不起作用,因为在混淆代码时类名会被更改。 您可能需要考虑在proguard配置文件(proguard-rules.pro)上添加一个例外,以排除从AbstractMigratorHelper扩展的任何类

 # Avoid errors when upgrading database migrators -keep public class * extends yourpackage.locationofyourclass.AbstractMigratorHelper 

我这样做的方式略有不同。

我将新的@DatabaseTable类和任何@DatabaseFields添加到现有的@DatabaseTable类并运行DatabaseConfigUtil。

然后我将向DatabaseUpgrader类添加一个新方法并修改我的DatabaseHelper,更改DATABASE_VERSION值和onUpdate方法

 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); } … } 

然后在DatabaseUpdater类中

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