greenDao架构升级

Dis*_*Dev 26 orm android greendao

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

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

在我的情况下,我的迁移非常简单 - 我不希望转换任何现有数据,我只需要在我的模式中添加一些新表,我怀疑这是一种相当常见的情况.

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

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

Dis*_*Dev 44

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

免责声明:虽然我意识到这个实现是针对我的场景的,但我认为对于像我这样使用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);
}
Run Code Online (Sandbox Code Playgroud)

不要删除所有表,而是查看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);
        }
}
Run Code Online (Sandbox Code Playgroud)

添加新列有异曲同工之处,但你必须写一些SQL或看看自动生成的SQL创建greenDao陈述和利用这些.

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

db.execSQL("ALTER TABLE 'EXISTING_TABLE' ADD 'NEW_COLUMN' INTEGER");
Run Code Online (Sandbox Code Playgroud)

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

  • 我们在哪里设置新版本号? (2认同)

ple*_*mik 9

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

public abstract class AbstractMigratorHelper {

public abstract void onUpgrade(SQLiteDatabase db);
}
Run Code Online (Sandbox Code Playgroud)

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

我会写一个例子

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");
 }
}
Run Code Online (Sandbox Code Playgroud)

在此之后,您需要在升级时实际调用的类上实现逻辑,在那里您需要删除以前的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;
            }


        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您仔细命名您的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
Run Code Online (Sandbox Code Playgroud)


Rob*_*oll 5

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

我将新的@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);
    }

    …
}
Run Code Online (Sandbox Code Playgroud)

然后在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<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);
        }

    }
}
Run Code Online (Sandbox Code Playgroud)