首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >greenDao模式升级

greenDao模式升级
EN

Stack Overflow用户
提问于 2013-04-22 18:27:13
回答 4查看 17.5K关注 0票数 26

我看到了关于使用绿色数据(这里)的模式升级/迁移的另一个问题。

在进行模式升级时,这个答案中有很多链接可供使用--但是,对于如何正确迁移数据,您并没有实际操作的示例,而且我也很难找到任何东西。

在我的例子中,我的迁移是非常直接的--我不希望转换任何现有的数据,我只需要向我的模式中添加一些新的表,我想这是一个相当常见的情况。

最好举一个具体的例子。

如果greenDao提供了一个类似于DevOpenHelper的类,只需添加以前在模式中不存在的新表/列,而不首先删除现有的tabes/data,那就太棒了。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-05-05 15:43:08

我终于有时间亲自钻研这个问题,并意识到在旧表中保留数据很容易添加一个新表。

免责声明:虽然我意识到这个实现是特定于我的场景,但我认为这对像我这样专门使用Android工具(greenDao)来处理安卓上的SQLite的人是有帮助的。我知道,对于那些从一开始就编写了自己的表创建查询的人来说,这是很常见的,但是对于那些没有在SQLite上使用DB的人来说,我认为这个例子会很有帮助。

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

在进行更改之前,DevOpenHelper.onUpgrade如下所示:

代码语言:javascript
复制
@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);
}

与其删除所有表,不如看看由createAllTables自动生成的GreenDao方法。

重写onUpgrade以检查"oldVersion“是否是您想要升级的对象,然后只调用”新“表的createTable方法。下面是我的onUpgrade方法现在的样子:

代码语言:javascript
复制
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的自动生成的generated语句并利用这些语句。

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

代码语言:javascript
复制
db.execSQL("ALTER TABLE 'EXISTING_TABLE' ADD 'NEW_COLUMN' INTEGER");

现在对我来说,我所需要做的就是添加新的表,这样它就会变得非常直接。希望其他人发现这是有用的。

票数 44
EN

Stack Overflow用户

发布于 2014-09-23 09:16:44

我做了一种稍微不同的方法来自动处理更新,不管前面的用户来自哪里。首先,我创建了一个在onUpgrade上实现SQLDatabase方法的类

代码语言:javascript
复制
public abstract class AbstractMigratorHelper {

public abstract void onUpgrade(SQLiteDatabase db);
}

之后,我将从这个类继承所有的移民助手。

我会写其中一个例子

代码语言:javascript
复制
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,以便定制一个类似于下面的类

代码语言:javascript
复制
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;
            }


        }
    }
}

因此,如果您很小心地命名了您的迁移助手(即MigrationHelper5完成了从模式5到模式6的迁移),那么您可以实现这个逻辑,然后在每个MigratorHelper类中使用您需要实现的所有execSQL代码来实现execSQL调用。

最后,请注意,如果您正在使用proguard,那么逐个类查找名称的方法可能无法工作,因为在混淆代码时会更改类名。您可能需要考虑在proguard配置文件上添加一个异常(pro保密规则. from ),以排除从AbstractMigratorHelper扩展的任何类。

代码语言:javascript
复制
# Avoid errors when upgrading database migrators

-keep public class * extends yourpackage.locationofyourclass.AbstractMigratorHelper
票数 9
EN

Stack Overflow用户

发布于 2013-08-16 06:56:18

我的做法略有不同。

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

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

代码语言:javascript
复制
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类中

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16154113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档