Android中LinkingObject的使用及Realm关联表相关技术问题
Realm表关联实现与常见问题解答
结合你给出的实体类代码,咱们逐一解决你提到的三个核心问题:
一、添加父表时不存在子表,如何添加RealmList?
首先要注意:Realm的RealmList不能为null,建议你先修改父表的实体类,把child字段初始化好,避免空指针问题:
@RealmClass open class ParentTable : RealmObject() { @PrimaryKey open var id : Long = 0 open var parentname : String? = null // 直接初始化RealmList,不要设为可空 var child = RealmList<ChildTable>() }
当添加父表时如果子表对象还不存在,你需要在Realm事务中先创建子表对象,再将其添加到父表的RealmList中,步骤如下:
// 获取Realm实例 val realm = Realm.getDefaultInstance() realm.executeTransaction { bgRealm -> // 1. 创建子表对象(如果子表还不存在,用createObject生成带主键的对象) val childId = 1L // 子表的主键值 val child = bgRealm.createObject(ChildTable::class.java, childId) child.childName = "测试子表" // 给子表设置其他属性 // 2. 创建或查询父表对象 val parentId = 1L // 父表的主键值 val parent = bgRealm.createObject(ParentTable::class.java, parentId) parent.parentname = "测试父表" // 3. 将子对象添加到父表的RealmList中 parent.child.add(child) } // 记得关闭Realm实例 realm.close()
如果子表对象已经存在,直接查询出子对象再添加到RealmList即可,逻辑是一样的。
二、父表与子表之间是否存在实时关联?
答案是肯定的,Realm的对象和集合都是动态代理对象,只要在同一个Realm实例的线程中,父子表的关联是实时同步的:
- 如果你修改了子表对象的属性(比如
childName),父表RealmList中对应的子对象会立刻更新,不需要重新查询; - 如果你从父表的
RealmList中移除某个子对象,该子对象的反向关联(如果用@LinkingObject设置了)也会实时更新; - 反过来,通过子表的
@LinkingObject查询关联的父表,结果也会随着父表的变化实时刷新。
举个实时更新的例子:
realm.executeTransaction { // 修改子表属性 val child = it.where(ChildTable::class.java).equalTo("id", 1L).findFirst() child?.childName = "更新后的子表名称" } // 查询父表,直接获取更新后的子表属性 val parent = realm.where(ParentTable::class.java).equalTo("id", 1L).findFirst() Log.d("Realm", parent?.child?.get(0)?.childName) // 输出:更新后的子表名称
三、如何迁移RealmList与@LinkingObject?
Realm的迁移需要实现Migration接口,并在配置中指定,分两种情况处理:
1. 迁移RealmList字段
比如原来的父表没有child字段,现在要新增这个RealmList<ChildTable>字段,迁移代码如下:
val customMigration = object : Migration { override fun migrate(realm: DynamicRealm, oldVersion: Long, newVersion: Long) { val schema = realm.schema var currentVersion = oldVersion // 版本从0升级到1,添加child字段 if (currentVersion < 1) { // 给ParentTable添加RealmList类型的child字段,关联ChildTable schema.get("ParentTable")?.addRealmListField("child", schema.get("ChildTable")!!) currentVersion = 1 } // 如果后续还有版本升级,可以继续添加判断 } } // 配置Realm时指定迁移和新版本号 val realmConfig = RealmConfiguration.Builder() .name("my_realm.db") .schemaVersion(1) .migration(customMigration) .build() // 初始化Realm Realm.setDefaultConfiguration(realmConfig)
如果是修改RealmList的关联类型(比如原来关联其他表,现在改成ChildTable),需要先移除旧字段,再添加新的RealmList字段。
2. 迁移@LinkingObject
@LinkingObject是Realm提供的反向关联查询,它本身不会存储在数据库中,而是基于正向关联的字段(比如父表的child)动态生成的结果。所以迁移时不需要针对@LinkingObject做任何数据库层面的操作,只要:
- 修改子表的实体类,添加
@LinkingObjects注解:
@RealmClass open class ChildTable : RealmObject() { @PrimaryKey open var id : Long = 0 open var childName : String? = null // 反向关联父表的child字段 @LinkingObjects("child") val parents: RealmResults<ParentTable>? = null }
- 确保正向关联的字段(父表的
child)已经存在于数据库中,@LinkingObjects就会自动生效,不需要修改迁移逻辑。
内容的提问来源于stack exchange,提问作者hanmolee
相关产品推荐
相关产品推荐

