Realm 数据库 升级(迁移) 采坑记录 —— 多么痛的领悟

今天 Stand-Up 会上 ,老大讲这周我们要结束 996 ,周六可以不用来加班 。前提是客户端解决完所有的 BUG 达到可上线的要求 ,下周一过来直接上线 。

哈哈哈哈哈 ,我估计他们明天还得来 。

 

 

Realm 数据库是一个很神奇的数据库 。接手这个项目是第一次使用 ,在国内找不到比较完善的文章   官方文档 Realm 。

官网截图

Realm 数据库 升级(迁移) 采坑记录 —— 多么痛的领悟_第1张图片

第一次数据出库的时候是因为两个版本的数据库名字不一样 。当时也算是费了一些时间去看这个数据库 。最后的做法是数据迁移 ,老数据库的数据迁移到新数据库并且废弃掉第一个数据库 。

 

昨天在数据库升级的时候再次出现问题 。

官方文档上的升级步骤就不罗列了 ,不知道是我的悟性不够还是文档写的太简单 ,总之就是按照文档走最后闪退 。


Realm 数据库升级/迁移 。

 

对已有 RealmObject 新增字段

1. 在 Application 里面初始化数据库 。

   /**
     * 初始化数据库
     */
  private void initRealm() {
        Realm.init(this);
        RealmConfiguration config = new RealmConfiguration.Builder()
                .name("cuour.realm")
                .schemaVersion(2)//数据库版本
                .modules(new CuourModule())
                .migration(new MyMigration())
                .build();
        Realm.setDefaultConfiguration(config);
        
    }

问题一 :只能在 Application 里面进行初始化吗 ?

当然不是 ,有一些朋友就只是在 Application 里面做 Realm.init(this);操作 。不过如果在项目里面多处地方调用Realm.getDefaultInstance(); 会报错 。

 

java.lang.IllegalArgumentException: Configurations cannot be different if used to open the same file. The most likely cause is that equals() and hashCode() are not overridden in the migration class: xxx.xxx.MyMigration

java.lang.IllegalArgumentException: Configurations cannot be different if used to open the same file. The most likely cause is that equals() and hashCode() are not overridden in the migration class: xxx.xxx.MyMigration

大概意思就是打开用一个文件配置不能相同 。怎么回事呢 ? 这就设置到 Ream 的 Close 问题 。解决方案有两种 。

1. RealmConfiguration 设置成单利 

2. 在使用完之后进行 Realm.close();

 

2. 更新数据库操作类 。 MyMigration

public class MyMigration implements RealmMigration {

    /**
     * 本地数据库升级的时候会自动回调一次
     * @param realm
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
        Log.i("Realm",oldVersion + "-----" + newVersion);
        RealmSchema schema=realm.getSchema();

        if(oldVersion == 1 && newVersion ==2){
            schema.get("VideoDownloadBean")
                    .addField("updateValue1", String.class)
                    .addField("updateValue2", String.class);
  oldVersion ++;

        }
}
}

3. 数据类 RealmObject

public class VideoDownloadBean extends RealmObject {

    @PrimaryKey
    private int lessonId; //课时id
    private String LessonName; //课时名称
    private boolean isClassroom; //班级/课程
    private int courseId; //课程id
    private String courseName; //课程名称
    private int classroomId; //班级id
    private String classroomName; //班级名称
    private long length;
    private String lessonItem;

    // Verison == 2 新增字段
    private String updateValue1;
    private String updateValue2;
        
    // ... 省略 get set 
}

 

4. 使用 RealmStudio 查看数据库

Realm 数据库 升级(迁移) 采坑记录 —— 多么痛的领悟_第2张图片

 

结束 。

对已有数据库增加新的 RealmObject 

1. 在 Application 里面初始化数据库

   private void initRealm() {
        Realm.init(this);
        RealmConfiguration config = new RealmConfiguration.Builder()
                .name("cuour.realm")
                .schemaVersion(3)//数据库版本
                .modules(new CuourModule())
                .migration(new MyMigration())
                .build();
        Realm.setDefaultConfiguration(config);

    }

2. 更改 modules 新增 RealmObject

@RealmModule(classes = {GenseeVodDownloadBean.class,
        VideoDownloadBean.class,
        M3U8DownloadBean.class,
        LocalVideoDataBean.class// version ==3 新增 RealmObject

})
public class CuourModule {
}

3. MyMigration 更新 

public class MyMigration implements RealmMigration {

    /**
     * 本地数据库升级的时候会自动回调一次
     *
     * @param realm
     * @param oldVersion
     * @param newVersion
     */
    @Override
    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
        Log.i("Realm", oldVersion + "-----" + newVersion);
        RealmSchema schema = realm.getSchema();

         if (oldVersion == 1 && newVersion == 2) {
            schema.get("VideoDownloadBean")
                    .addField("updateValue1", String.class)
                    .addField("updateValue1", String.class);
            oldVersion++;
        }

        if (oldVersion == 2 && newVersion == 3) { // Version 3 
            schema.create("LocalVideoDataBean")
                    .addField("courseId", String.class, FieldAttribute.PRIMARY_KEY)
                    .addField("title", String.class)
                    .addField("classroomId", String.class)
                    .addField("lessonId", String.class)
                    .addField("type", String.class)
                    .addField("lastPlayPostion", String.class)
                    .addField("clientWatchLength", String.class)
                    .addField("isReportData", boolean.class);

            oldVersion++;
        }

       

    }
}

4. 运行 查看 数据库

Realm 数据库 升级(迁移) 采坑记录 —— 多么痛的领悟_第3张图片

 

END、

 

 

 

奇异事件 

昨天在做这一块的时候 ,一直给我闪退 。what ! what !!what !!!

闪退的错误有 

1.  已经被添加

io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:

    - Class 'LocalVideoDataBean' has been added.

io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors:
    - Class 'LocalVideoDataBean' has been added.

字面意思是 LocalVideoDataBean 已经被添加 。我查看数据库的时候并没有被添加 。你要问怎么解决的 ,我现在想想并没有该什么东西 ,上述的更新数据库方法跟官网的几乎一样 。昨晚我确实是按照这个流程走的 。   

PS :有小伙伴在遇到这个错误 ,可以直接在下面评论一起来看一下这个问题 。(虽然不能保证秒回复但是不会让你等太久)

 

2. 不能打开同一个配置文件

java.lang.IllegalArgumentException: Configurations cannot be different if used to open the same file. The most likely cause is that equals() and hashCode() are not overridden in the migration class: xxx.xxx.xxx.xxx.bean.MyMigration

 

举一个:

在首页我打开同一个数据库在数据最操作 ,在下载管理里面我也打开同一数据库做操作 。使用的是如下代码

 RealmConfiguration config = new RealmConfiguration.Builder()
                .name("cuour.realm")
                .schemaVersion(3)//数据库版本
                .modules(new CuourModule())
                .migration(new MyMigration())
                .build();
        realm = Realm.getInstance(config);

如果在项目中每次使用都数据库的时候都调用以上代码 ,就会出现上述错误 。 字面意思就是你打开多次同一配置的文件 。

可以使用单例

public class RealmHelper {
    private static RealmConfiguration realmConfiguration;

    private static RealmHelper realmHelper;

    private RealmHelper() {
        init();
    }

    public RealmConfiguration getRealmConfiguration() {
        return realmConfiguration;
    }

    public static RealmHelper getInstanca() {
        if (realmHelper == null) {
            synchronized (RealmHelper.class) {
                if (realmHelper == null) {
                    realmHelper = new RealmHelper();
                }
            }
        }
        return realmHelper;
    }

    public void init() {

        if (realmConfiguration == null) {
            synchronized (RealmHelper.class) {
                if (realmConfiguration == null) {
                    realmConfiguration = new RealmConfiguration.Builder()
                            .name("cuour.realm")
                            .schemaVersion(3)//数据库版本
                            .modules(new CuourModule())
                            .migration(new MyMigration())
                            .build();
                }
            }
        }

    }


}

 

使用时候调用

   RealmConfiguration config = RealmHelper.getInstanca().getRealmConfiguration();
        Realm realm = Realm.getInstance(config);

 

OKOK

 

PS :升级有其他问题  可以交流交流 。

 

PS :明天应该可以休息了 ,结束万恶的 996 。

你可能感兴趣的:(心得随便记录)