繁体   English   中英

TypeORM:与实体中定义的 where 子句的关系

[英]TypeORM : relation with where clause defined in entity

我想创建一个 SalesOrder 实体,它与同一实体有 2 个 OneToMany 关系,但标准不同。

最终目标是检索这样的地址:

const salesOrder = await SalesOrder.findOne(1, {
    relations: ['receiverAddress', 'senderAddress']
});
console.log(salesOrder.receiverAddress)
console.log(salesOrder.senderAddress)

我不知道如何在 SalesOrder 实体中按类型过滤地址关系

我想做这样的事情:

// SalesOrder.ts
@Entity()
export class SalesOrder extends BaseEntity {
  @Column()
  @PrimaryGeneratedColumn()
  id: number

  @OneToMany(SalesOrderAddress, salesOrderAddress => salesOrderAddress, {
    where: {
      type: 'receiver' // join condition salesOrderAddress.type = 'receiver'
    }
  })
  receiverAddress: SalesOrderAddress

  @OneToMany(SalesOrderAddress, salesOrderAddress => salesOrderAddress, {
    where: {
      type: 'sender' // join condition salesOrderAddress.type = 'sender'
    }
  })
  senderAddress: SalesOrderAddress
}

问题:在 typeorm 装饰器中没有处理where子句。

是否有可能得到类似的东西(不使用查询生成器)?

我知道我可以使用 2 个 OneToOne 关系,但这意味着 SalesOrder 数据库包含两个外键:receiverAddressId 和 senderAddressId。 我更喜欢使用 OneToMany 关系,因为它允许在 SalesOrderAddress 上只有一个外键(例如 salesOrderId)。

在您的情况下,我会考虑创建自定义方法来获取所需的信息。 检查该示例:

import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToOne } from 'typeorm';

@Entity({ name: 'Address' })
export class Address extends BaseEntity {
  @PrimaryGeneratedColumn({ type: 'int' })
  id: number;

  @Column({ type: 'varchar', length: 20 })
  type: 'receiver' | 'sender';

  @Column({ type: 'nvarchar', length: 1024 })
  value: string;

  // Put the prop that connects this entity to SalesOrder
  @ManyToOne(SalesOrder, ref => ref.addresses)
  salesOrder: SalesOrder;
}

@Entity({ name: 'SalesOrder' })
export class SalesOrder extends BaseEntity {
  @PrimaryGeneratedColumn({ type: 'int' })
  id: number;

  // Put the prop that connects this entity to Address
  @OneToMany(Address, ref => ref.salesOrder)
  addresses: Address[];

  // Create a generic method to filter
  private static getTypeAddresses(id: number, type: 'receiver' | 'sender'): Promise<Address[]> {
    if (typeof id !== 'number') {
      throw new Error('The entity\'s id must be a number');
    }

    return Address
      .createQueryBuilder('Address')
      .select([ 'Address' ])
      .innerJoin(
        'Address.salesOrder',
        'SalesOrder',
        'SalesOrder.id = :id',
        { id: id }
      )
      .where(
        'type = :type',
        { type }
       )
      .getMany();
  }

  // Later, create your methods to obtain easifully your address
  static getReceiverAddresses(id: number): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(id, 'receiver');
  }

  static getSenderAddresses(id: number): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(id, 'sender');
  }

  getReceiverAddresses(): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(this.id, 'receiver');
  }

  getSenderAddresses(): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(this.id, 'sender');
  }
}

使用示例:

const salesOrder = await SalesOrder.findOne({ id: 1 });
console.log(await salesOrder.getReceiverAddresses());
console.log(await salesOrder.getSenderAddresses());

如果您不想向实体的 class 添加方法,请考虑创建 controller class 或更方便的过程。 例如:

import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToOne } from 'typeorm';

@Entity({ name: 'Address' })
export class Address extends BaseEntity {
  @PrimaryGeneratedColumn({ type: 'int' })
  id: number;

  @Column({ type: 'varchar', length: 20 })
  type: 'receiver' | 'sender';

  @Column({ type: 'nvarchar', length: 1024 })
  value: string;

  // Put the prop that connects this entity to SalesOrder
  @ManyToOne(SalesOrder, ref => ref.addresses)
  salesOrder: SalesOrder;
}

@Entity({ name: 'SalesOrder' })
export class SalesOrder extends BaseEntity {
  @PrimaryGeneratedColumn({ type: 'int' })
  id: number;

  // Put the prop that connects this entity to Address
  @OneToMany(Address, ref => ref.salesOrder)
  addresses: Address[];
}

export class SalesOrderCtrl extends SalesOrder {
  private static getTypeAddresses(id: number, type: 'receiver' | 'sender'): Promise<Address[]> {
    if (typeof id !== 'number') {
      throw new Error('The entity\'s id must be a number');
    }

    return Address
      .createQueryBuilder('Address')
      .select([ 'Address' ])
      .innerJoin(
        'Address.salesOrder',
        'SalesOrder',
        'SalesOrder.id = :id',
        { id: id }
      )
      .where(
        'type = :type',
        { type }
       )
      .getMany();
  }

  static getReceiverAddresses(id: number): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(id, 'receiver');
  }

  static getSenderAddresses(id: number): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(id, 'sender');
  }

  getReceiverAddresses(): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(this.id, 'receiver');
  }

  getSenderAddresses(): Promise<Address[]> {
    return SalesOrder.getTypeAddresses(this.id, 'sender');
  }
}

使用示例:

const salesOrder = await SalesOrderCtrl.findOne({ id: 1 });
console.log(await salesOrder.getReceiverAddresses());
console.log(await salesOrder.getSenderAddresses());

我想创建一个 SalesOrder 实体,它与同一实体有 2 个 OneToMany 关系,但标准不同。

最终目标是检索这样的地址:

const salesOrder = await SalesOrder.findOne(1, {
    relations: ['receiverAddress', 'senderAddress']
});
console.log(salesOrder.receiverAddress)
console.log(salesOrder.senderAddress)

我不知道如何在 SalesOrder 实体中按类型过滤地址关系

我想做这样的事情:

// SalesOrder.ts
@Entity()
export class SalesOrder extends BaseEntity {
  @Column()
  @PrimaryGeneratedColumn()
  id: number

  @OneToMany(SalesOrderAddress, salesOrderAddress => salesOrderAddress, {
    where: {
      type: 'receiver' // join condition salesOrderAddress.type = 'receiver'
    }
  })
  receiverAddress: SalesOrderAddress

  @OneToMany(SalesOrderAddress, salesOrderAddress => salesOrderAddress, {
    where: {
      type: 'sender' // join condition salesOrderAddress.type = 'sender'
    }
  })
  senderAddress: SalesOrderAddress
}

问题:在 typeorm 装饰器中没有处理where子句。

是否有可能得到类似的东西(不使用查询生成器)?

我知道我可以改用 2 个 OneToOne 关系,但这意味着 SalesOrder 数据库包含两个外键:receiverAddressId 和 senderAddressId。 我更喜欢使用 OneToMany 关系,因为它允许在 SalesOrderAddress 上只有一个外键(例如 salesOrderId)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM