Android数据库Realm 升级,更换主键,更换字段类型

2019-07-22  本文已影响0人  二全

该篇文章主要讲解在android上使用Realm,关于升级的文章!
1.新增一个表(或者说新增一个类让其成为数据表)
2.更换已经存在的表中的字段类型(例如Int 类型更换为String类型)
3.更换已经存在的表中的主键

升级数据库很简单,在调用Realm实例的时候配置config时传入我们自己写好的MyMigration类即可,当然数据库的version也需要增加

object RealmHelper {
    private fun getRealmConfig(): RealmConfiguration {
        return RealmConfiguration.Builder()
                .name(RealmConstant.DB_NAME)
                .schemaVersion(RealmConstant.DB_VERSION)
                .migration(MyMigration())
                .build()
    }

    @JvmStatic
    fun getRealmInstance():Realm{
        return Realm.getInstance(getRealmConfig())
    }
}

接下来你要实现上述说的1,2,3只要在MyMigration类中实现即可

1.新增一个表

Realm数据库和传统SQL数据库增加表不一样,Realm只要增加一个表就要升级!新增表的类
例如我第一版本的DB_VERSION=0,现在我要新增一个表
a.DB_VERSION=1
b.实现新增的表类
c.在MyMigration处理升级

open class RedBookChapter(@PrimaryKey var chapterId: Int = -1, @Index var bookId: String = "") : RealmObject()

class MyMigration : RealmMigration {
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        var oldV = oldVersion
        val schema = realm.schema
        if (oldV == 0L) {
            val bookChapterSchema = schema.create("RedBookChapter")
            bookChapterSchema?.let {
                it.addField("chapterId", Int::class.java, FieldAttribute.PRIMARY_KEY)
                        .addField("bookId", String::class.java, FieldAttribute.INDEXED)
                        .setRequired("bookId", true)
               
            }
           oldV++
        }
    }


    /**
     *  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:
     *  com.apusapps.reader.provider.realm.MyMigration
     */
    override fun hashCode(): Int {
        return MyMigration::class.java.hashCode()
    }

    override fun equals(other: Any?): Boolean {
        if (other == null) {
            return false
        }
        return other is MyMigration
    }
}

这样在每次操作数据库时,自然检查版本号就处理升级了!

2.更换已经存在的表中的字段的类型(例如Int 类型更换为String类型)

新增表中的字段很简单,addField即可,但是这里要说的是更换表中已经存在的字段的类型,并且字段名不变(即只更换字段的类型)
例如我第上一版本的DB_VERSION=1,现在我要更换字段的类型
a.DB_VERSION=2
b.处理更换字段的类
c.在MyMigration处理升级

原来的类
open class BookColl(@PrimaryKey var bookId: String = "",
                    var briefIntro: String? = "",
                    var majorCateId: Int? = -1,
                    var majorCateName: String? = "",
                    var minorCateId: Int? = -1,
                    var minorCateName: String? = ""
) : RealmObject()
修改后的类
open class BookColl(@PrimaryKey var bookId: String = "",
                    var briefIntro: String? = "",
                    var majorCateId: String? = "",
                    var majorCateName: String? = "",
                    var minorCateId: String? = "",
                    var minorCateName: String? = ""
) : RealmObject()
class MyMigration : RealmMigration {
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        var oldV = oldVersion
        val schema = realm.schema
        if (oldV == 0L) {
            val bookChapterSchema = schema.create("RedBookChapter")
            bookChapterSchema?.let {
                it.addField("chapterId", Int::class.java, FieldAttribute.PRIMARY_KEY)
                        .addField("bookId", String::class.java, FieldAttribute.INDEXED)
                        .setRequired("bookId", true)
                
            }

            oldV++
        }

        if (oldV == 1L) {
            val bookCollSchema = schema.get("BookColl")
            bookCollSchema?.let {
                it.addField("majorCateId_temp", String::class.java)
                        .addField("minorCateId_temp", String::class.java)
                        .transform { obj ->
                            obj.setString("majorCateId_temp", obj.getInt("majorCateId").toString())
                            obj.setString("minorCateId_temp", obj.getInt("minorCateId").toString())
                        }
                        .removeField("majorCateId")
                        .removeField("minorCateId")
                        .renameField("majorCateId_temp", "majorCateId")
                        .renameField("minorCateId_temp", "minorCateId")
               
            }
            oldV++
        }
    }


    /**
     *  这里的hashCode,和equals同上面一样,这里省略
     */
   
}

说明下:

1.命名临时的字段majorCateId_temp,minorCateId_temp
2.将DB_VERSION=1中老用户的majorCateId和minorCateId这些字段迁移到DB_VERSION=2中的临时字段是上
3.移除老的字段
4.重新命名,将majorCateId_temp等字段改为之前的字段

3.更换已经存在的表中的主键

因为DB_VERSION=1时,新增了RedBookChapter,但是我的主键用错了,需要重新更换主键。
因为中间已经有了DB_VERSION=2了,所以这里DB_VERSION=3

a.DB_VERSION=3
b.处理更换主键的类
c.在MyMigration处理升级

更换主键之前的类
open class RedBookChapter(@PrimaryKey var chapterId: Int = -1, @Index var bookId: String = "") : RealmObject()
更换主键后的类
open class RedBookChapter(@PrimaryKey var hashCode:String = "",
                             var chapterId: Int = -1, @Index var bookId: String = "") : RealmObject()

注意这里的hasCode不是真正的hashCode,是我用bookId和chapterId拼装的:bookId.plus(chapterId.toInt())
要知道一个类的hashCode会随时变的,自己百度了解吧

class MyMigration : RealmMigration {
    override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) {
        var oldV = oldVersion
        val schema = realm.schema
        if (oldV == 0L) {
            val bookChapterSchema = schema.create("RedBookChapter")
            bookChapterSchema?.let {
                it.addField("chapterId", Int::class.java, FieldAttribute.PRIMARY_KEY)
                        .addField("bookId", String::class.java, FieldAttribute.INDEXED)
                        .setRequired("bookId", true)
                
            }

            oldV++
        }

        if (oldV == 1L) {
            val bookCollSchema = schema.get("BookColl")
            bookCollSchema?.let {
                it.addField("majorCateId_temp", String::class.java)
                        .addField("minorCateId_temp", String::class.java)
                        .transform { obj ->
                            obj.setString("majorCateId_temp", obj.getInt("majorCateId").toString())
                            obj.setString("minorCateId_temp", obj.getInt("minorCateId").toString())
                        }
                        .removeField("majorCateId")
                        .removeField("minorCateId")
                        .renameField("majorCateId_temp", "majorCateId")
                        .renameField("minorCateId_temp", "minorCateId")
               
            }
             oldV++
        }

        if (oldV == 2L) {
            val bookRedChapter = schema.get("RedBookChapter")
            bookRedChapter ?.let {
                it.addField("hashCode", String::class.java)
                        .addField("chapterId_temp",Int::class.java)
                        .transform { obj ->
                            obj.setString("hashCode", obj.getString("bookId").plus(obj.getInt("chapterId")))
                            obj.setInt("chapterId_temp", obj.getInt("chapterId"))
                        }
                        .removeField("chapterId")
                        .renameField("chapterId_temp","chapterId")
                        .addPrimaryKey("hashCode")
                        .setRequired("hashCode",true)
               
            }

           oldV++
        }
    }

    /**
     *  这里的hashCode,和equals同上面一样,这里省略
     */
}

到这里文章开头说的1,2,3要完成的事已经处理完毕了
其实只要处理好自己原来的类
处理好MyMigration即可

上一篇下一篇

猜你喜欢

热点阅读