使用场景

版本升级后,增加表、删除表、增加字段、删减字段等。为了保留原始数据,需要将数据进行迁移。使用GreenDao数据库的升级操作该如何进行呢?

思路

创建临时表TMP_,将原先表数据迁移过去

删除所有原表

创建新表

将TMP_表数据复制到新表,最后将TMP_表删除

实现

添加字段并编译

private static void addUser(Schema schema) {

Entity user = schema.addEntity("UserInfo");

user.addIdProperty();

user.addStringProperty("name").notNull();

user.addStringProperty("idNumber").notNull();

user.addStringProperty("department").notNull();

user.addStringProperty("place");// 新增字段

user.addStringProperty("project");

user.addStringProperty("updateTime");

user.addBooleanProperty("isSelected");

}

编译后,会产生新的UserInfo、UserInfoDao、DaoMaster、DaoSession。我们将新产生的类,替换原先的类。

实现MigrationHelper

public class MigrationHelper {

private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";

private static MigrationHelper instance;

static MigrationHelper getInstance() {

if(instance == null) {

instance = new MigrationHelper();

}

return instance;

}

@SafeVarargs

final void migrate(Database db, Class extends AbstractDao, ?>>... daoClasses) {

generateTempTables(db, daoClasses);

DaoMaster.dropAllTables(db, true);

DaoMaster.createAllTables(db, false);

restoreData(db, daoClasses);

}

@SafeVarargs

private final void generateTempTables(Database db, Class extends AbstractDao, ?>>... daoClasses) {

for (Class extends AbstractDao, ?>> daoClass : daoClasses) {

DaoConfig daoConfig = new DaoConfig(db, daoClass);

String divider = "";

String tableName = daoConfig.tablename;

String tempTableName = daoConfig.tablename.concat("_TEMP");

ArrayList properties = new ArrayList<>();

StringBuilder createTableStringBuilder = new StringBuilder();

createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

for (int j = 0; j < daoConfig.properties.length; j++) {

String columnName = daoConfig.properties[j].columnName;

if (getColumns(db, tableName).contains(columnName)) {

properties.add(columnName);

String type = null;

try {

type = getTypeByClass(daoConfig.properties[j].type);

} catch (Exception exception) {

// Crashlytics.logException(exception);

}

createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

if (daoConfig.properties[j].primaryKey) {

createTableStringBuilder.append(" PRIMARY KEY");

}

divider = ",";

}

}

createTableStringBuilder.append(");");

db.execSQL(createTableStringBuilder.toString());

String insertTableStringBuilder = "INSERT INTO " + tempTableName + " (" +

TextUtils.join(",", properties) +

") SELECT " +

TextUtils.join(",", properties) +

" FROM " + tableName + ";";

db.execSQL(insertTableStringBuilder);

}

}

@SafeVarargs

private final void restoreData(Database db, Class extends AbstractDao, ?>>... daoClasses) {

for (Class extends AbstractDao, ?>> daoClass : daoClasses) {

DaoConfig daoConfig = new DaoConfig(db, daoClass);

String tableName = daoConfig.tablename;

String tempTableName = daoConfig.tablename.concat("_TEMP");

List properties = new ArrayList<>();

for (int j = 0; j < daoConfig.properties.length; j++) {

String columnName = daoConfig.properties[j].columnName;

if (getColumns(db, tempTableName).contains(columnName)) {

properties.add(columnName);

}

}

String insertTableStringBuilder = "INSERT INTO " + tableName + " (" +

TextUtils.join(",", properties) +

") SELECT " +

TextUtils.join(",", properties) +

" FROM " + tempTableName + ";";

db.execSQL(insertTableStringBuilder);

db.execSQL("DROP TABLE " + tempTableName);

}

}

private String getTypeByClass(Class> type) throws Exception {

if(type.equals(String.class)) {

return "TEXT";

}

if(type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {

return "INTEGER";

}

if(type.equals(Boolean.class)) {

return "BOOLEAN";

}

// Crashlytics.logException(exception);

throw new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));

}

private static List getColumns(Database db, String tableName) {

List columns = new ArrayList<>();

Cursor cursor = null;

try {

cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);

if (cursor != null) {

columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));

}

} catch (Exception e) {

Log.v(tableName, e.getMessage(), e);

e.printStackTrace();

} finally {

if (cursor != null)

cursor.close();

}

return columns;

}

}

修改DaoMaster

修改数据库版本: public static final int SCHEMA_VERSION = 4;

在DevOpenHelper的onUpgrade方法中,修改升级操作。

在升级时,需将所有的Dao类加至migrate方法中。示例只有一个Dao类。

@Override

public void onUpgrade(Database db, int oldVersion, int newVersion) {

Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");

if (newVersion > oldVersion) {

// 升级、数据库迁移操作

MigrationHelper.getInstance().migrate(db, UserInfoDao.class);

}else {

// 默认操作

dropAllTables(db, true);

onCreate(db);

}

}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐