美文网首页
Android数据库Realm 升级,更换主键,更换字段类型

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

作者: 二全 | 来源:发表于2019-07-22 10:26 被阅读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即可

    相关文章

      网友评论

          本文标题:Android数据库Realm 升级,更换主键,更换字段类型

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