React Native Realm无多态支持下的交易实体关联方案咨询
React Native + Realm 多态场景替代实现方案
针对你在Realm中处理交易实体关联的需求,以下是几种实用的替代实现模式:
1. 抽象父类 + 类型标记(最接近多态思路)
Realm不支持多态关联,但可以通过定义抽象父类统一交易参与实体,再用类型标记区分具体类型:
// 抽象父类:统一所有交易参与实体的基础属性 class TransactionParticipant extends Realm.Object { static schema = { name: 'TransactionParticipant', properties: { id: 'string', type: 'string', // 标记具体类型:'Income'/'Wallet'/'Expense' }, primaryKey: 'id', }; } // 子类:继承父类并扩展自身属性 class Income extends TransactionParticipant { static schema = { name: 'Income', properties: { source: 'string', // 收入来源 amount: 'decimal128', }, }; } class Wallet extends TransactionParticipant { static schema = { name: 'Wallet', properties: { name: 'string', balance: 'decimal128', }, }; } class Expense extends TransactionParticipant { static schema = { name: 'Expense', properties: { category: 'string', // 支出分类 amount: 'decimal128', }, }; } // 交易模型:直接关联父类 class Transaction extends Realm.Object { static schema = { name: 'Transaction', properties: { id: 'string', from: 'TransactionParticipant', to: 'TransactionParticipant', amount: 'decimal128', createdAt: 'date', }, primaryKey: 'id', }; }
使用方式
- 创建交易时,直接传入子类实例:
realm.write(() => { const salaryIncome = realm.create('Income', { id: 'inc_001', type: 'Income', source: '工资', amount: new Realm.Decimal128('8000'), }); const mainWallet = realm.create('Wallet', { id: 'wal_001', type: 'Wallet', name: '主钱包', balance: new Realm.Decimal128('0'), }); // 创建Income到Wallet的交易 realm.create('Transaction', { id: 'tx_001', from: salaryIncome, to: mainWallet, amount: new Realm.Decimal128('8000'), createdAt: new Date(), }); }); - 查询时通过
type字段判断具体类型,直接访问子类属性:const transactions = realm.objects('Transaction'); transactions.forEach(tx => { if (tx.from.type === 'Income') { console.log(`收入来源:${tx.from.source}`); } else if (tx.from.type === 'Wallet') { console.log(`转出钱包:${tx.from.name}`); } });
2. 类型标记 + 通用ID关联(灵活易扩展)
给交易模型添加类型标记和通用ID字段,手动关联对应实体:
class Transaction extends Realm.Object { static schema = { name: 'Transaction', properties: { id: 'string', type: 'string', // 标记交易类型:'income_to_wallet'/'wallet_to_wallet'/'wallet_to_expense' fromId: 'string', fromType: 'string', // 标记转出方类型:'Income'/'Wallet' toId: 'string', toType: 'string', // 标记转入方类型:'Wallet'/'Expense' amount: 'decimal128', createdAt: 'date', }, primaryKey: 'id', }; } // Income/Wallet/Expense模型保持独立,各自定义主键id
使用方式
- 创建交易时记录对应实体的ID和类型:
realm.write(() => { realm.create('Transaction', { id: 'tx_002', type: 'wallet_to_expense', fromId: 'wal_001', fromType: 'Wallet', toId: 'exp_001', toType: 'Expense', amount: new Realm.Decimal128('200'), createdAt: new Date(), }); }); - 查询时根据类型和ID获取关联实体:
function getParticipant(type, id) { return realm.objects(type).filtered(`id == '${id}'`)[0]; } transactions.forEach(tx => { const from = getParticipant(tx.fromType, tx.fromId); const to = getParticipant(tx.toType, tx.toId); console.log(`交易:${from?.name || from?.source} → ${to?.name || to?.category}`); });
3. 专用字段分组(简单场景快速实现)
给交易模型添加多组可选关联字段,通过交易类型标记使用哪一组:
class Transaction extends Realm.Object { static schema = { name: 'Transaction', properties: { id: 'string', type: 'string', // 转出方字段组 fromIncome: 'Income?', fromWallet: 'Wallet?', // 转入方字段组 toWallet: 'Wallet?', toExpense: 'Expense?', amount: 'decimal128', createdAt: 'date', }, primaryKey: 'id', }; }
使用方式
- 创建交易时仅设置对应类型的字段:
realm.write(() => { realm.create('Transaction', { id: 'tx_003', type: 'wallet_to_wallet', fromWallet: mainWallet, toWallet: secondaryWallet, amount: new Realm.Decimal128('1000'), createdAt: new Date(), }); }); - 查询时根据类型读取对应字段:
transactions.forEach(tx => { switch(tx.type) { case 'income_to_wallet': console.log(`${tx.fromIncome.source} → ${tx.toWallet.name}`); break; case 'wallet_to_expense': console.log(`${tx.fromWallet.name} → ${tx.toExpense.category}`); break; } });
方案选择建议
- 优先选抽象父类+类型标记:最接近多态设计,代码结构清晰,Realm对象关联自动维护一致性。
- 复杂场景选类型标记+通用ID关联:灵活性高,适合后续可能扩展更多交易参与实体的情况。
- 简单场景选专用字段分组:实现成本低,但字段冗余,扩展性较差。
内容的提问来源于stack exchange,提问作者Original BBQ Sauce
相关产品推荐
相关产品推荐

