React Native中Realm数据库如何实现1:n关系两张表关联
Realm 一对多表关联实现方案
你当前用int类型存city_id手动做外键的写法不是Realm推荐的关联方式,Realm提供了原生的对象引用能力,直接定义关联关系即可实现1:n映射,不需要手动维护外键,查询和关联操作性能更高,也不会出现数据不一致问题。
第一步:修改两个Schema定义
核心改动点共2处:
- 在「多」端(活动表
Detail),把原来的int类型city_id替换为Town类型的对象引用,标记活动所属城市 - 在「一」端(城市表
Town),通过反向链接(backlink)属性自动关联该城市下的所有活动,不需要手动维护列表数据
修改后的完整Schema代码如下:
const CitySchema = { name: "Town", properties: { _id: "int", // 主键 name: "string", // 城市名称 region: "string", // 所属区域 street: "string", // 街道地址 city: "string", // 邮编+城市名 phone: "int", // 联系电话 ico: "int", // 机构编号 dic: "string", // 税号 logo: "string", // logo地址 lat: "double", // 纬度 lng: "double", // 经度 // 新增:反向关联所有归属当前城市的活动,不需要手动赋值 events: { type: "linkingObjects", objectType: "Detail", property: "belongCity" } }, primaryKey: "_id", }; const EventSchema = { name: "Detail", properties: { _id: "int", // 主键 // 替换原来的city_id: "int",直接关联所属城市对象 belongCity: "Town", eventName: "string", // 活动名称 eventDescription: "string", // 活动描述 }, primaryKey: "_id", };
第二步:初始化Realm
如果是首次使用没有历史数据,直接传入schema即可;如果已有存量历史数据,需要增加版本号做轻量迁移,把旧的city_id映射为新的对象引用:
(async () => { const realm = await Realm.open({ path: "myrealm", schema: [CitySchema, EventSchema], // 有旧数据的话打开下面的版本配置,执行迁移 // schemaVersion: 2, // onMigration: (oldRealm, newRealm) => { // if (oldRealm.schemaVersion < 2) { // const oldEvents = oldRealm.objects("Detail"); // const newEvents = newRealm.objects("Detail"); // for (let i = 0; i < oldEvents.length; i++) { // const oldEvent = oldEvents[i]; // const newEvent = newEvents[i]; // // 用原来存的city_id找到对应城市对象,赋值给关联字段 // newEvent.belongCity = newRealm.objectForPrimaryKey("Town", oldEvent.city_id); // } // } // } }); })();
常用关联操作示例
- 新建城市并绑定活动:
realm.write(() => { // 先创建城市 const town = realm.create("Town", { _id: 1, name: "Obec Jalubí", region: "Zlínský kraj", street: "Jalub 1", city: "123 45 Jalubí", phone: 999999999, ico: 123456789, dic: "CZ123456789", logo: "https://www.jalubi.eu/skins/jalubi.eu_lego2/images/crest.png", lat: 50.1163, lng: 18.4279 }); // 创建活动时直接绑定所属城市 realm.create("Detail", { _id: 1, belongCity: town, eventName: "Balloon popping", eventDescription: "This event is about...." }) })
- 查询某城市下所有活动:直接取城市的
events属性即可,这是Realm自动维护的活动列表
const targetTown = realm.objectForPrimaryKey("Town", 1); const townEvents = targetTown.events; // 拿到该城市下所有关联的活动
- 查询某活动所属城市:直接取活动的
belongCity属性即可
const targetEvent = realm.objectForPrimaryKey("Detail", 1); const eventBelongTown = targetEvent.belongCity; // 拿到活动归属的城市对象
注意事项
- 不要同时保留旧的
city_id字段和对象关联字段,避免出现数据不一致 - 用
linkingObjects定义的反向关联属性是只读的,不需要手动往events列表里push活动,只要给活动设置了belongCity属性,对应城市的events列表会自动更新 - 如果业务允许活动暂时不绑定城市,可以把
belongCity的类型改成"Town?"标记为可选字段
内容的提问来源于stack exchange,提问作者Tomáš Gabriel
相关产品推荐
相关产品推荐

