美文网首页
GreenDao 3.x 数据库版本升级 迁移数据

GreenDao 3.x 数据库版本升级 迁移数据

作者: 腐化的木头 | 来源:发表于2017-12-27 16:30 被阅读0次

    网上搜索很多都是3.0以下的版本数据迁移配置,在此记录自己3.2.2版本的数据迁移的配置

    1.修改之前的数据迁移类

    public class MigrationHelper {
      
    private static MigrationHelper instance;
    
    public static MigrationHelper getInstance() {
        if(instance == null) {
            instance = new MigrationHelper();
        }
        return instance;
    }
    
    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
    }
    
    private void generateTempTables(Database 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) {
                        Log.e(TAG,exception.toString());
                    }
    
                    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(Database 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()));
        Log.e(TAG,exception.toString());
        throw exception;
    }
    
    private static List<String> getColumns(Database 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;
     }
    }
    

    2.创建一个类继承 DaoMaster.OpenHelper

    public class UpdateOpenHelper extends DaoMaster.OpenHelper {
    
    
    public UpdateOpenHelper(Context context, String name) {
        super(context, name);
    }
    
    public UpdateOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }
    
    //此方法用于3.0版本之前的升级方案 须将MigrationHelper中的DB 类型更改为SQLiteDatabase
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
        if (oldVersion < newVersion) {
            Log.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
            //            MigrationHelper.getInstance().migrate(db, UserDao.class);
            //更改过的实体类(新增的不用加)   更新UserDao文件 可以添加多个  XXDao.class 文件
            //             MigrationHelper.getInstance().migrate(db, UserDao.class,XXDao.class);
        }
    }
    
    
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
        Log.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
        if (oldVersion < newVersion) {
            MigrationHelper.getInstance().migrate(db, UserDao.class);
            //更改过的实体类(新增的不用加)   更新UserDao文件 可以添加多个  XXDao.class 文件
          //MigrationHelper.getInstance().migrate(db, UserDao.class, XXDao.class);
      }
     }
    }
    

    3.修改GreenDao的初始化

    修改前的初始化
        mHelper = new DaoMaster.DevOpenHelper(this, "test-db.db", null);
        db = mHelper.getWritableDatabase();
        // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
        mDaoMaster = new DaoMaster(db);
        mDaoSession = mDaoMaster.newSession();
        //获取对应的数据库表对象
        userDao = mDaoSession.getUserDao();
    
    修改后
        mHelper = new UpdateOpenHelper(this, "test-db.db", null);
        db = mHelper.getWritableDatabase();
        // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。
        mDaoMaster = new DaoMaster(db);
        mDaoSession = mDaoMaster.newSession();
        //获取对应的数据库表对象
        userDao = mDaoSession.getUserDao();
    
    我的DB管理类
    public class DBManager {
    // 是否加密
    public static final boolean ENCRYPTED = true;
    
    private static final String DB_NAME = "test-db.db";
    private static DbManager mDbManager;
    private static DaoMaster.DevOpenHelper mDevOpenHelper;
    private static DaoMaster mDaoMaster;
    private static DaoSession mDaoSession;
    
    private Context mContext;
    
    private DBManager(Context context) {
        this.mContext = context;
        // 初始化数据库信息
        mDevOpenHelper = new DaoMaster.DevOpenHelper(context, DB_NAME);
        getDaoMaster(context);
        getDaoSession(context);
    }
    
    public static DBManager getInstance(Context context) {
        if (null == mDBManager) {
            synchronized (DBManager.class) {
                if (null == mDBManager) {
                    mDBManager = new DBManager(context);
                }
            }
        }
        return mDBManager;
    }
    
    /**
     * 获取可读数据库
     *
     * @param context
     * @return
     */
    public static SQLiteDatabase getReadableDatabase(Context context) {
        if (null == mDevOpenHelper) {
            getInstance(context);
        }
        return mDevOpenHelper.getReadableDatabase();
    }
    
    /**
     * 获取可写数据库
     *
     * @param context
     * @return
     */
    public static SQLiteDatabase getWritableDatabase(Context context) {
        if (null == mDevOpenHelper) {
            getInstance(context);
        }
        return mDevOpenHelper.getWritableDatabase();
    }
    
    /**
     * 获取DaoMaster
     *
     * 判断是否存在数据库,如果没有则创建数据库
     * @param context
     * @return
     */
    public static DaoMaster getDaoMaster(Context context) {
        if (null == mDaoMaster) {
            synchronized (DbManager.class) {
                if (null == mDaoMaster) {
                    UpdateOpenHelper helper = new UpdateOpenHelper(context,DB_NAME,null);
                    mDaoMaster = new DaoMaster(helper.getWritableDatabase());
                }
            }
        }
        return mDaoMaster;
    }
    
    /**
     * 未添加版本更新前的获取方法
     * 获取DaoMaster
     *
     * @param context
     * @return
     */
    //    public static DaoMaster getDaoMaster(Context context) {
    //        if (null == mDaoMaster) {
    //            synchronized (DbManager.class) {
    //                if (null == mDaoMaster) {
    //
    //                    mDaoMaster = new DaoMaster(getWritableDatabase(context));
    //                }
    //            }
    //        }
    //        return mDaoMaster;
    //    }
    
    /**
     * 获取DaoSession
     *
     * @param context
     * @return
     */
    public static DaoSession getDaoSession(Context context) {
        if (null == mDaoSession) {
            synchronized (DbManager.class) {
                mDaoSession = getDaoMaster(context).newSession();
            }
        }
    
        return mDaoSession;
     }
    }
    

    4.注意事项

    实体类中新增字段,必须为Long,Double,Integer,Float,String类型,否则在数据迁移时会出现空指针异常

    你可以查看对应的Dao类中createTable()方法 double等类型会在字段后出现REAL NOT NULL

       /** Creates the underlying database table. */
       public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"USER\" (" + //
                "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
                "\"NAME\" TEXT," + // 1: name
                "\"PASSWORD\" TEXT," + // 2: password
                "\"AGE\" TEXT," + // 3: age
                "\"A\" REAL NOT NULL );"); // 4: a   为double类型
        }
    

    相关文章

      网友评论

          本文标题:GreenDao 3.x 数据库版本升级 迁移数据

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