该篇文章主要讲解在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即可