簡體   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