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

该篇文章主要讲解在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同上面一样,这里省略 */}

【Android数据库Realm|Android数据库Realm 升级,更换主键,更换字段类型】说明下:
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即可

    推荐阅读