美文网首页Android
关于Android数据库升级

关于Android数据库升级

作者: 树新蜜蜂 | 来源:发表于2019-07-31 11:48 被阅读0次

    GreenDao数据库升级

    第一步:升级数据库版本号
    首先存在着数据库 并且版本号只能高不能低

    // app:build.gradle
    apply plugin: 'com.android.application'
    apply plugin: 'org.greenrobot.greendao'
    
    android {
        ...
    }
    
    greendao{
        schemaVersion 2 // 版本号+1
    }
    
    dependencies {
        ...
    }
    
    
    

    第2步:修改数据库对应的实体类
    在原有的基础上 增 删 改(字段,类型,权限)

    @Entity
    public class Person {
    
        @Id(autoincrement = true)
        private Long id;
    
        @NotNull
        private String name;
    
        private Integer age; // 增加一个年龄字段
    }
    
    
    

    第3步:自定义OpenHelper对象
    自定义一个类去继承DaoMaster.OpenHelper重写数据库的升级方法onUpgrade() 代码如下

    // 继承DaoMaster.OpenHelper
    public class MyOpenHelper extends DaoMaster.OpenHelper {
    
        public MyOpenHelper(Context context, String name) {
            super(context, name);
        }
    
        public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
            super(context, name, factory);
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            super.onUpgrade(db, oldVersion, newVersion);
            // 升级数据库
            MigrationHelper.migrate(db, PersonDao.class);
        }
    }
    
    
    

    第4步:替换默认的DevOpenHelper
    将之前版本中的DaoMaster.OpenHelper替换为我们重写后的OpenHelper 其他的不用改变

    private DaoSession initGreenDao() {
        // 替换为自定义的OpenHelper对象
        DaoMaster.OpenHelper openHelper = new MyOpenHelper(this, "cumulus.db");
        SQLiteDatabase database = openHelper.getReadableDatabase();
        DaoMaster daoMaster = new DaoMaster(database);
        return daoMaster.newSession();
    }
    
    
    

    可以同时升级多张表

    升级工具类
    1.根据旧版本的方案(generateTempTables方法)创建临时表
    2.将所有数据导入此新表(generateTempTables方法)
    3.删除旧版本的所有表(DaoMaster.dropAllTables方法)
    4.创建新版本的表(DaoMaster.createAllTables方法)
    5.从临时更新新版本的表(restoreData方法)
    6.删除所有临时表(restoreData方法)

    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.text.TextUtils;
    import android.util.Log;
    
    import com.crashlytics.android.Crashlytics;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import de.greenrobot.dao.AbstractDao;
    import de.greenrobot.dao.internal.DaoConfig;
    import greendao.DaoMaster;
    
    
    /**
     * Created by pokawa on 18/05/15.
     */
    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;
    
        public static MigrationHelper getInstance() {
            if(instance == null) {
                instance = new MigrationHelper();
            }
            return instance;
        }
    
        public void migrate(SQLiteDatabase db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            generateTempTables(db, daoClasses);
            DaoMaster.dropAllTables(db, true);
            DaoMaster.createAllTables(db, false);
            restoreData(db, daoClasses);
        }
    
        private void generateTempTables(SQLiteDatabase db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            for(int i = 0; i < daoClasses.length; i++) {
                DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
    
                String divider = "";
                String tableName = daoConfig.tablename;
                String tempTableName = daoConfig.tablename.concat("_TEMP");
                ArrayList<String> 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());
    
                StringBuilder insertTableStringBuilder = new StringBuilder();
    
                insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
                insertTableStringBuilder.append(TextUtils.join(",", properties));
                insertTableStringBuilder.append(") SELECT ");
                insertTableStringBuilder.append(TextUtils.join(",", properties));
                insertTableStringBuilder.append(" FROM ").append(tableName).append(";");
    
                db.execSQL(insertTableStringBuilder.toString());
            }
        }
    
        private void restoreData(SQLiteDatabase db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
            for(int i = 0; i < daoClasses.length; i++) {
                DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
    
                String tableName = daoConfig.tablename;
                String tempTableName = daoConfig.tablename.concat("_TEMP");
                ArrayList<String> 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);
                    }
                }
    
                StringBuilder insertTableStringBuilder = new StringBuilder();
    
                insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
                insertTableStringBuilder.append(TextUtils.join(",", properties));
                insertTableStringBuilder.append(") SELECT ");
                insertTableStringBuilder.append(TextUtils.join(",", properties));
                insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");
    
                StringBuilder dropTableStringBuilder = new StringBuilder();
    
                dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
    
                db.execSQL(insertTableStringBuilder.toString());
                db.execSQL(dropTableStringBuilder.toString());
            }
        }
    
        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";
            }
    
            Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
            Crashlytics.logException(exception);
            throw exception;
        }
    
        private static List<String> getColumns(SQLiteDatabase db, String tableName) {
            List<String> 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.java类中调用它的示例:

    @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by migrating all tables data");
    
            MigrationHelper.getInstance().migrate(db,
                    UserDao.class,
                    ItemDao.class);
        }
    

    相关文章

      网友评论

        本文标题:关于Android数据库升级

        本文链接:https://www.haomeiwen.com/subject/vcuzrctx.html