【问题标题】:TypeORM: when can join condition be omitted?TypeORM:什么时候可以省略连接条件?
【发布时间】:2021-11-10 13:40:25
【问题描述】:

我正在使用 TypeORM 进行两个项目。在其中一个项目中,当我使用查询构建器选择数据并且查询包含连接时,生成的查询不包含连接条件,生成以下查询:

SELECT *
FROM `alarms`.`faultLog` `fl`
INNER JOIN `alarms`.`alarm` `a`

这给出了 2 543 922 个结果,而不是预期的 1743 个结果。

使用的查询:

return this.faultsRepository
            .createQueryBuilder('fl')
            .innerJoin('fl.alarm', 'a')
            .getRawMany();

如果我将条件添加为innerjoin 函数的第三个参数,则以下无效查询:

SELECT *
FROM `alarms`.`faultLog` `fl`
INNER JOIN `alarms`.`alarm` `a`
ON  AND (`a`.`id` = fl.alarmId)

如果我将查询中的属性名称更改为alarm 而不是fl.alarm,那么生成的查询就可以了。

在另一个项目中,我有一个类似的查询,它不会造成问题,其中生成的查询包含连接条件:

return this._recipeRepository
            .createQueryBuilder('r')
            .innerJoin('r.type', 'rType')
            .innerJoin('r.equipment', 'eq')
            .innerJoin('r.versions', 'rVers')
            .select([
              'r.id as id',
              'r.name as name',
              'rType.name as type',
              'r.SKU as sku',
              'r.description as description',
              'rVers.id as versionId',
              'rVers.versionNumber as version'
            ])
            .getRawMany();

我检查了 TypeORM 初始化和存储库配置,一切似乎都是等效的,所以我不明白这里发生了什么。

精简后的实体:

@Entity({
  name: "alarm",
  database: 'alarms',
  synchronize: false,
})
export class AlarmEntity {
  @PrimaryGeneratedColumn({
    name: 'id',
    type: 'integer'
  })
  @Generated('increment')
  id: number;

  @Column({
    name: 'description',
    type: 'varchar',
    length: '200'
  })
  description: string;

  @OneToMany(
   () => FaultLogEntity,
   faultLog => faultLog.alarm,
   {
     cascade: true
   }
  )
  faultLogs: FaultLogEntity[];
}

@Entity({
  name: "faultLog",
  database: 'alarms',
  synchronize: false
})
export class FaultLogEntity {
  @PrimaryGeneratedColumn({
    name: 'id',
    type: 'integer'
  })
  id: number;

  @Column({type: 'datetime'})
  timestampAppearance:Date;

  @OneToMany(() => AlarmEntity, alarm => alarm.faultLogs)
  @JoinColumn({ name: 'alarmId' })
  alarm: AlarmEntity;
}

存储库配置:

export const alarmsProviders = [
  {
    provide: "AlarmEntity",
    useFactory: (connection: Connection) => connection.getRepository(AlarmEntity),
    inject: [Constants.DATABASE_CONNECTION]
  },
  {
    provide: "FaultLogEntity",
    useFactory: (connection: Connection) => connection.getRepository(FaultLogEntity),
    inject: [Constants.DATABASE_CONNECTION]
  },
]

数据库连接:

export const databaseProviders = [
  {
    provide: Constants.DATABASE_CONNECTION,
    useFactory: async () => await createConnection({
      type: 'mysql',
      host: 'localhost',
      port: 3000,
      username: 'xxx',
      password: 'xxx',
      database: 'alarms',
      synchronize: false,
      logging: true,
      entities: [
        __dirname + '/../**/*.entity{.ts,.js}',
      ],
    }),
  },
];

在应用模块中的使用:

@Module({
  controllers: [AppController, AlarmsController],
  providers: [AppService, AlarmsService, ...databaseProviders, ...alarmsProviders]
})
export class AppModule {
}

所以,主要问题是:TypeORM 需要什么来自动推断连接条件?我在这里错过了什么?

【问题讨论】:

  • MySQL 语法允许不带 ON 子句的 INNER JOIN - 在这种情况下,它充当 CROSS JOIN。
  • @Akina 是的,这不是我想要实现的。重点是:在一个项目中,生成的查询包含这个条件,而没有在queryBuilder查询中添加,而在另一个中则没有。我正在寻找我所缺少的生成查询始终包含此条件而不明确指定它。

标签: mysql node.js typescript nestjs typeorm


【解决方案1】:

其中一个实体应该具有多对一关系,您应该尝试将 FaultLogEntity 中的关系更改为多对一

【讨论】:

  • 就是这样!我忽略了这一点。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 2010-10-01
  • 2014-01-24
  • 2015-05-11
  • 2012-07-28
相关资源
最近更新 更多