TypeORM 0.3.7与0.3.20关联加载差异问题求助
TypeORM 0.3.x关联加载行为变更问题
问题代码
async findOneByAddress(address: Address): Promise<Account | null> { const where: FindOptionsWhere<Account> = { account: { subacct: { address: Equal(address.toString()) }, }, }; return await this.accountsRepository.findOne({ where, relations: ['user', 'account', 'account.subacct'], }); }
问题现象
在TypeORM 0.3.7中,上述查询会加载该Account关联的全部5个utxoAccountAddresses;但升级到0.3.20版本后,仅加载where条件中匹配的那一个。该行为在find方法和查询构建器查询中均存在。
解答
1. 这是有意的破坏性变更,而非Bug
TypeORM在0.3.x版本迭代中调整了关联加载逻辑:旧版本里,关联实体的过滤条件仅用于筛选主实体,不会限制关联实体的加载范围;新版本中,当通过嵌套关联的条件筛选主实体时,关联加载会自动继承该过滤规则,仅返回匹配的关联项。官方称此变更为让关联加载行为更符合直觉,避免意外加载大量无关数据。
2. 恢复旧逻辑的两种方案
方案一:拆分查询,先查主实体再全量加载关联
先通过条件找到目标Account,再单独加载其所有关联的subacct:
async findOneByAddress(address: Address): Promise<Account | null> { // 筛选符合条件的主实体 const targetAccount = await this.accountsRepository.findOne({ where: { account: { subacct: { address: Equal(address.toString()) }, }, }, relations: ['user', 'account'] }); if (!targetAccount) return null; // 全量加载该Account的所有subacct关联 await this.accountsRepository .createQueryBuilder('account') .leftJoinAndSelect('account.account.subacct', 'subacct') .where('account.id = :id', { id: targetAccount.id }) .getOne(); return targetAccount; }
方案二:使用QueryBuilder显式控制关联加载
通过QueryBuilder分别定义主实体的过滤条件和关联实体的加载规则,避免关联自动继承主查询的过滤逻辑:
async findOneByAddress(address: Address): Promise<Account | null> { return this.accountsRepository .createQueryBuilder('mainAccount') .leftJoinAndSelect('mainAccount.user', 'user') .leftJoinAndSelect('mainAccount.account', 'account') .leftJoinAndSelect('account.subacct', 'subacct') // 仅对主实体应用地址过滤,关联实体全量加载 .where('subacct.address = :address', { address: address.toString() }) .getOne(); }
内容的提问来源于stack exchange,提问作者synic
相关产品推荐
相关产品推荐

