如何使用 innerJoinAndSelect 将两个表合并为一个?

Posted

技术标签:

【中文标题】如何使用 innerJoinAndSelect 将两个表合并为一个?【英文标题】:How to use innerJoinAndSelect to merge two tables into one? 【发布时间】:2021-07-30 18:47:42 【问题描述】:

大家!我有两个相关的表,其中一个包含第二个表记录的 id 列。所以我想从第二个表中提取几个属性并将它们与第一个表的结果连接起来。

我遇到的问题是当我尝试通过 SQL 字符串(即SELECT * FROM `characters` `c` INNER JOIN `money` `m` ON `c`.`bank` = `m`.`id` WHERE uuid = ?)进行查询时——一切正常。但是,当我通过 TypeORM 执行相同操作时,queryBuilder 仅返回第一个表 (characters) 中的数据。

我的聊天者实体:

export default class Character extends BaseEntity 
  @PrimaryGeneratedColumn()
  public id: number;

  @Column()
  uuid: number;

  ...

  @OneToOne(() => Money)
  @JoinColumn()
  bank: Money;

  ...

  public static async findByUuid(uuid: number): Promise<Character> 
    return await getManager()
      .createQueryBuilder(Character, "c")
      .innerJoinAndSelect(Money, "m", "c.bank = m.id")
      .where("uuid = :uuid ",  uuid )
      .getOne();
  

我的实体:

export default class Money extends BaseEntity 
  @PrimaryGeneratedColumn()
   public id: number;

  @Column()
  type: number;

  @Column()
  holder: string;

  @Column()
  balance: number;

我尝试将c.bank = m.id 替换为c.bankId = m.id,但也没有成功。我试图删除@OneToOne 关系,但我得到了同样的效果。我打开了“日志记录”选项并复制了生成的 SQL 字符串,然后我通过 phpMyAdmin 执行了它......它工作了!似乎 TypeORM 修改了查询的结果,只给了我第一个表的行。我不明白出了什么问题。请帮忙。

【问题讨论】:

【参考方案1】:

您应该能够通过两种方式做到这一点:

1。使用QueryBuilder(就像你尝试过的那样):

const character = await getManager()
      .createQueryBuilder(Character, "c")
      .innerJoinAndSelect("c.bank", "bank")
      .where("c.uuid = :uuid ",  uuid )
      .getOne();
return character;

2。使用findOne:

const character = await getManager()
      .getRepository(Character)
      .findOne( relations: ["bank"], where:  uuid  );
return character;

现在您应该可以使用character.bank 访问bank

更新:要从 characters 表中删除外键 bankId,您可以执行以下操作。

@OneToOne(() => Money,  createForeignKeyConstraints: false )
bank: Money;

见the reference from typeorm documentation。

正如您所说,如果其他服务器试图将 id 保存到 bank 字段中,那将是有问题的,因为您的 Character 实体的 bank 属性是 Money 类型。如果您将关系名称更改为其他名称以避免冲突,那就更好了。

希望这会有所帮助。干杯? !!!

【讨论】:

好的,我试试。有没有办法从第二个表中只提取特定的 fiekda?如果我想防止生成额外的列“bankId”怎么办?例如,我不想创建另一个我不会使用的实体。所以我没有指出这两个表之间的任何关系,但我希望将它们联合起来(或者,如果可能,只需要我需要的字段)。 您的意思是要阻止在characters 表中生成bankId 列,但还是想加入它们? 是的,完全正确。我的数据库被另一台服务器使用,该服务器将 id 存储到“bank”字段中(但是这个被删除了,而是生成了“bankId”列)。所以我担心潜在的冲突。无论如何,我很高兴知道所有方法来做到这一点(不创建额外的列、实体等) bankId 列的生成是因为我们在Character 实体中使用了@JoinColumn() 注释。我将用如何从您的实体中删除外键引用来更新我的答案。不过,您可能需要对其进行测试才能确定。 您的解决方案有效,但仍创建了“bankId”列...我尝试插入带有“bank”字段的行,但不幸的是,我发现了此列没有的错误不存在。我想知道,有没有办法在没有关系的情况下做出类似的效果?

以上是关于如何使用 innerJoinAndSelect 将两个表合并为一个?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用静态库传输资源文件(如何将资源包装在包中)?

如何将 CameraX 与 PreviewView 一起使用?

如何将 groupBy 与 MagicalRecord 一起使用?

如何将 ASTextNode 与 TTTAttributedLabel 一起使用

我们如何将 OCP 与委托一起使用?

如何使用 AngularJS 将文件上传到 Google Drive