Realm关联关系与嵌入对象:如何仅存储RealmObject引用?
解决Realm中仅存储对象引用且无需自动更新的问题
针对你的需求,这里有两种实用方案,无需依赖自动同步的RealmList:
方案一:存储关联对象的ObjectId列表
Realm虽然不强制外键约束,但你完全可以直接存储ObjectId的普通列表,替代托管的RealmList<RealmObject>。这种方式既实现了“存储引用”的目的,又不会触发自动更新——因为存的只是ID,而非Realm的托管关联。
修改后的代码示例:
class Actor : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" var age: Int? = null // 存储关联电影的ObjectId列表,而非直接存Movie对象 var movieIds: List<ObjectId> = listOf() } class Movie : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // 存储关联演员的ObjectId列表 var actorIds: List<ObjectId> = listOf() var roles: List<String> = listOf() }
需要获取关联对象时,手动通过ObjectId查询即可:
// 示例:根据Actor的movieIds查询对应的电影 val actor = realm.find(Actor::class.java, actorId) val movies = actor?.movieIds?.mapNotNull { movieId -> realm.find(Movie::class.java, movieId) }
这种方式最接近你熟悉的SQL外键思路,完全符合“少用RealmObject类”的需求,不需要额外的交叉表。
方案二:存储非托管的对象副本
如果你需要直接存储对象的快照(而非ID),可以把关联对象转换成非托管副本,再存入普通List中。Realm的copyFromRealm()方法能把托管对象转换成脱离Realm管理的副本,后续原对象变更不会影响这个副本。
注意:Realm不允许直接在RealmObject中存储List<RealmObject>(非RealmList),所以需要先把Actor/Movie转换成普通数据类,再存储数据类的列表:
- 定义对应的数据类:
data class ActorDto( val _id: ObjectId, val name: String, val age: Int? ) data class MovieDto( val _id: ObjectId, val name: String, val roles: List<String> )
- 修改RealmObject类:
class Actor : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" var age: Int? = null // 存储电影的非托管副本列表 var movies: List<MovieDto> = listOf() } class Movie : RealmObject { var _id: ObjectId = ObjectId() var name: String = "" // 存储演员的非托管副本列表 var actors: List<ActorDto> = listOf() var roles: List<String> = listOf() }
- 存入副本时的操作:
// 示例:将托管的Movie对象转换成Dto存入Actor val managedMovie = realm.find(Movie::class.java, movieId) val movieDto = managedMovie?.let { MovieDto(it._id, it.name, it.roles) } realm.executeTransaction { val actor = it.find(Actor::class.java, actorId) actor?.movies = actor?.movies.orEmpty() + listOfNotNull(movieDto) }
这种方式存的是对象的快照,完全不受原对象变更影响,但需要额外定义数据类,适合需要直接使用对象属性而不想手动查询的场景。
内容的提问来源于stack exchange,提问作者Daniel M.
相关产品推荐
相关产品推荐

