ORMLite update of the database

家住魔仙堡 提交于 2019-11-27 01:56:41

问题


I'm actually developing an app which is using ORMLite library (which is wonderful btw) but I'm a beginner using it.

I have a question about the update of the database inside the device.

Let's say that someone download my app on the Google Play. Few months later I will certainly populate some tables with new entries.

When this person is doing an update of the app, how can I just update the database with my new entries and keep the old ones inside it.

To be more clear, imagine that the user answered questions in my app. When I will introduce new questions, how can I insert them in the db when he updates my app and keep the questions that have already been answered ?


回答1:


When this person is doing an update of the app, how can I just update the database with my new entries and keep the old ones inside it.

The idea is to use the version number that is passed to the onUpgrade(...) method. With ORMLite, the OrmLiteSqliteOpenHelper.onUpgrade(...) method takes an oldVersion and newVersion number. You then can write conversion code into your application that is able to convert the data from the old format and update the schema.

For more information, see the ORMLite docs on the subject:

http://ormlite.com/docs/upgrade-schema

To quote, you could do something like the following:

if (oldVersion < 2) {
  // we added the age column in version 2
  dao.executeRaw("ALTER TABLE `account` ADD COLUMN age INTEGER;");
}
if (oldVersion < 3) {
  // we added the weight column in version 3
  dao.executeRaw("ALTER TABLE `account` ADD COLUMN weight INTEGER;");
}

If you have existing data that you need to convert then you should do the conversions in SQL if possible.

Another alternative would be to have an Account entity and an OldAccount entity that point to the same table-name. Then you can read in OldAccount entities using the oldAccountDao, convert them to Account entities, and then update them using the accountDao back to the same table. You need to be careful about object caches here.




回答2:


I do it this way:

@Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {

    switch (oldVersion) {
    case 1:
        updateFromVersion1(database, connectionSource, oldVersion, newVersion);
        break;
    case 2:
        updateFromVersion2(database, connectionSource, oldVersion, newVersion);
        break;
    default:
        // no updates needed
        break;
    }

}

private void updateFromVersion1(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
    // do some stuff here
    onUpgrade(database, connectionSource, oldVersion + 1, newVersion);
}

private void updateFromVersion2(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
    // do some stuff here
    onUpgrade(database, connectionSource, oldVersion + 1, newVersion);
}

This will incrementally update the users db independent from which db version he is coming.




回答3:


Little information, is not clear whether the changes you have table structure.

a) If you do not change the database structure.

1 In the new version of your program when you start checking a previously saved version (eg in preferences) with the current (see PackageManager.getPackageInfo)

saved = 0 - User just installed the new version

saved < current - User updates your program

2 Add new data to base

3 Save current version on preferences

b) If the table structure has changed (added or remove fields)

1 Increase the version number of your database (see your extends OrmLiteSqliteOpenHelper class)

2 When the user first runs into your program, method 'onUpgrade' will be called (in your extends OrmLiteSqliteOpenHelper class) which will be transferred to old and new version numbers.

  • Read the existing data in the cache (temp)
  • recreate table
  • Add the data from the cache + your new data



回答4:


I don't like to drop database at every upgrade, or write an update code after I add each field, so ...

I'm trying to do it like this:

@Override
public void onUpgrade(SQLiteDatabase database, ConnectionSource connectionSource, int oldVersion, int newVersion) {
    ArrayList<String> tableNames = getTableNames(database);
    for (Class clazz : daoClasses) {
        try {
            Annotation annotation = clazz.getAnnotation(DatabaseTable.class);
            if (annotation != null && annotation instanceof DatabaseTable) {
                String tableName = ((DatabaseTable) annotation).tableName();
                if (tableName.isEmpty()) {
                    tableName = clazz.getSimpleName().substring(0, 1).toLowerCase() + clazz.getSimpleName().substring(1);
                }
                if(!tableNames.contains(tableName)){
                    TableUtils.createTable(connectionSource, clazz);
                } else {
                    addColumns(database, tableName, clazz);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

private ArrayList<String> getTableNames(SQLiteDatabase database){
    ArrayList<String> tableNames = new ArrayList<>();
    Cursor cursor = database.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);
    if (cursor.moveToFirst()) {
        while ( !cursor.isAfterLast() ) {
            tableNames.add(cursor.getString(0));
            cursor.moveToNext();
        }
    }
    cursor.close();
    return tableNames;
}

private void addColumns(SQLiteDatabase database, String tableName, Class clazz){
    Cursor mCursor = database.rawQuery("SELECT * FROM " + tableName + " LIMIT 0", null);
    for (Field field : clazz.getDeclaredFields()) {
        try {
            DatabaseField annotationField = field.getAnnotation(DatabaseField.class);
            if (annotationField != null && !annotationField.foreign()){
                String columnName = field.getName();
                boolean hasColumn = mCursor.getColumnIndex(columnName) != -1;
                if (!hasColumn) {
                    String columnType = field.getType().getSimpleName();
                    if(columnType.equals(String.class.getSimpleName())){
                        columnType = "TEXT";
                    } else {
                        columnType = columnType.toUpperCase();
                    }
                    database.execSQL(MessageFormat.format("ALTER TABLE `{0}` ADD COLUMN {1} {2};", tableName, columnName, columnType));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    mCursor.close();
}

I hope this code can be better.

Here, i don't delete old tables and columns that were removed from dao's, and I don't create foreign fields (I'm not sure if i need it).



来源:https://stackoverflow.com/questions/13782084/ormlite-update-of-the-database

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!