React Native中Realm DB迁移生成UUID遇主键重复及值为空问题
问题分析与解决方案
核心问题
- UUID设置未生效:迁移时给
FATHER和SON对象设置的UUID未被正确写入,导致所有SON的uuid字段为空字符串,触发主键重复错误。 - Realm 11迁移逻辑变化:从Realm 10升级到11后,迁移时操作
newRealm对象的方式发生了变化,直接遍历newRealm.objects()并修改的方式不再可靠。 - 查询逻辑失效:若Schema中已移除旧的
id_father字段,filtered(id_father = ${fatherObject.id_father})会返回空集或所有SON对象,导致关联关系设置错误。
解决步骤
1. 确认Schema定义正确性
确保FATHER和SON的Schema已将uuid设为主键,且字段类型为Realm.BSON.UUID:
const FatherSchema = { name: 'FATHER', primaryKey: 'uuid', properties: { id: 'int?', // 保留旧主键作为可选字段,迁移完成后可移除 uuid: 'UUID', // 必填主键 // 其他业务字段... } }; const SonSchema = { name: 'SON', primaryKey: 'uuid', properties: { id: 'int?', uuid: 'UUID', father_uuid: 'UUID', // 关联FATHER的uuid id_father: 'int?' // 保留旧关联字段,迁移完成后可移除 } };
2. 修改迁移函数逻辑
通过旧Realm对象与新Realm对象的索引对应来设置UUID,确保每个对象都能正确赋值:
export const realmParams = { path: 'db.realm', migration: (oldRealm: Realm, newRealm: Realm) => { if(oldRealm.schemaVersion <= 34) { // 建立旧FATHER id到新uuid的映射 const fatherIdMap = new Map<number, Realm.BSON.UUID>(); // 处理FATHER对象 const oldFathers = oldRealm.objects('FATHER'); const newFathers = newRealm.objects('FATHER'); for (let i = 0; i < oldFathers.length; i++) { const uuid = new Realm.BSON.UUID(); newFathers[i].uuid = uuid; fatherIdMap.set(oldFathers[i].id, uuid); } // 处理SON对象 const oldSons = oldRealm.objects('SON'); const newSons = newRealm.objects('SON'); for (let i = 0; i < oldSons.length; i++) { const sonUuid = new Realm.BSON.UUID(); newSons[i].uuid = sonUuid; // 通过旧id_father映射到新的father_uuid newSons[i].father_uuid = fatherIdMap.get(oldSons[i].id_father)!; } } }, schema: [FatherSchema, SonSchema], schemaVersion: 35, }
3. 额外排查点
- 迁移函数未执行:若日志无输出,检查旧数据库的
schemaVersion是否确实≤34。可卸载应用清除旧数据后重新测试,确保从低版本schema升级。 - 第三方UUID库兼容:若使用
uuid.v4(),需转换为Realm UUID对象:new Realm.BSON.UUID(uuid.v4()),避免因类型不匹配导致赋值失效。
内容的提问来源于stack exchange,提问作者LittleFish
相关产品推荐
相关产品推荐

