You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 05:59:55