KMM集成Realm/Atlas时Schema验证失败:未知类型PelletToNumberUsedMapEntry
问题翻译
我正在开发一个Kotlin Multiplatform(KMM)应用,尝试与Realm/Atlas集成。调用Realm.open(it)时抛出如下异常:
IllegalStateException@29576} "java.lang.IllegalStateException:
[RLM_ERR_SCHEMA_VALIDATION_FAILED]: Schema validation failed due to
the following errors: Property 'PelletInsertionVisit.pelletMapAsList'
of type 'array' has unknown object type 'PelletToNumberUsedMapEntry'
相关类代码:
class PelletInsertionVisit : RealmObject { @PrimaryKey var _id: String = "" var visitDate = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) var pelletsUsed: RealmList<Pellet> = realmListOf() var pelletMapAsList: RealmList<PelletToNumberUsedMapEntry> = realmListOf() // 记录 pellet 名称到使用数量的映射 var signedInUser: String = "UNKNOWN" // 执行更新操作的用户名 override fun toString(): String { return "PelletInsertionVisit(visitDate=$visitDate, pelletsUsed=$pelletsUsed, pelletMap=$pelletMapAsList, signedInUserUserName='$signedInUser')" } }
嵌入式类代码:
class PelletToNumberUsedMapEntry : EmbeddedRealmObject { var pelletKey: String = "NOTSET" var numberUsed: Int = 0 }
调用Realm.open(it)前的配置代码:
private fun setupRealmSync() { val user = runBlocking { appServiceInstance.currentUser } val config = user?.let { SyncConfiguration .Builder( it, setOf(UserAccount::class,Pellet::class, PelletInsertionVisit::class, PelletLot::class, Patient::class, Practice::class ) ) .initialSubscriptions(rerunOnOpen = true) { realms -> add( realms.query<PelletInsertionVisit>(), name = "Pellet Insertion Visit info", updateExisting = true ) add(realms.query<PelletLot>(), name = "Pellet info", updateExisting = true) add(realms.query<Patient>(), name = "Patient info", updateExisting = true) add(realms.query<Practice>(), name = "Practice info", updateExisting = true) add(realms.query<UserAccount>(), name = "UserAccount info", updateExisting = true) } .build() } }
目前PelletInsertionVisit已在MongoDB Compass中可见,但系统无法识别PelletToNumberUsedMapEntry类。我原本以为嵌入式对象无需额外配置,请问这是否是问题所在?
解决方案
问题的核心正是嵌入式对象PelletToNumberUsedMapEntry未被添加到Realm同步配置的类集合中。虽然嵌入式对象依赖父对象存在,不能独立存储,但在KMM的Realm Sync配置里,所有被引用的Realm对象(包括嵌入式对象)都需要显式声明,否则Realm无法识别该类型,导致Schema验证失败。
具体修改步骤
在SyncConfiguration.Builder的类集合参数中,添加PelletToNumberUsedMapEntry::class:
SyncConfiguration .Builder( it, setOf(UserAccount::class, Pellet::class, PelletInsertionVisit::class, PelletLot::class, Patient::class, Practice::class, PelletToNumberUsedMapEntry::class) // 新增该嵌入式类 ) .initialSubscriptions(rerunOnOpen = true) { realms -> // 订阅逻辑保持不变 add(realms.query<PelletInsertionVisit>(), name = "Pellet Insertion Visit info", updateExisting = true) add(realms.query<PelletLot>(), name = "Pellet info", updateExisting = true) add(realms.query<Patient>(), name = "Patient info", updateExisting = true) add(realms.query<Practice>(), name = "Practice info", updateExisting = true) add(realms.query<UserAccount>(), name = "UserAccount info", updateExisting = true) } .build()
补充说明
- 你的
PelletToNumberUsedMapEntry继承EmbeddedRealmObject的写法是正确的,无需修改。 - 云端Atlas中已存在的
PelletInsertionVisit集合,在修改配置后重新同步时,Realm会自动适配嵌入式对象的Schema(只要本地与云端Schema兼容)。
内容的提问来源于stack exchange,提问作者user443654

