【问题标题】:TypeORM Sharing One Entity Between Two Other EntitiesTypeORM 在两个其他实体之间共享一个实体
【发布时间】:2021-07-04 09:50:39
【问题描述】:

我正在使用 TypeORM 开发 NestJS 应用程序,并且有一个 Person 实体和一个 Business 实体。这些实体中的每一个都可以有 0 个或多个 Addresses。无论是Business 还是Person,地址字段都是相同的。因此,我想将所有地址放在一个表中,而不是管理 PersonAddressBusinessAddress 表(前提是这是设计我的数据库的“正确”方式)。

目前,这里是我的PersonAddress 实体的一部分:

// person.entity.ts
export class Person {
  @OneToMany(() => Address, (address) => address.person, { cascade: true})
  addresses: PersonAddress[]
}

// address.entity.ts
export class Address {

  @ManyToOne(() => Person, (person) => person.addresses)
  person: Person
}

我相信对于 TypeORM,这是执行此操作的正确方法,但我希望能够删除 AddressPerson 中的引用,以便我可以为 Business 使用相同的实体。

现在,我的问题分为两部分:

  1. 我想要的设计是设计数据库的正确方法吗?我有使用数据库和查询它们的经验,但没有设计它们。如果我想要做的是糟糕的数据库设计,那么我将继续为BusinessPerson 的地址创建一个单独的实体。
  2. 如果我想要的设计是正确的,我如何在 TypeORM 中定义实体来实现这个结果?

【问题讨论】:

    标签: database-design nestjs typeorm


    【解决方案1】:
    1. 我想要的设计是设计数据库的正确方法吗?

    是的,您想要一个指定数据库。一般来说,database normalization 有一些规则,一般来说,除非您有充分的理由,否则您希望遵守这些规则。这些规则通常已由您的 ORM 应用,例如每个表都需要有一个 id 列。

    1. 如何在 TypeORM 中定义实体以实现此结果?

    TypeOrm 让您可以单方面定义多对一关系,但不能反过来定义 source

    没有@ManyToOne,@OneToMany 就无法存在。如果要使用@OneToMany,则需要@ManyToOne。但是,不需要相反:如果您只关心@ManyToOne 关系,则可以在相关实体上不使用@OneToMany 的情况下定义它。

    那就是:

    person.entity.ts

    export class Person {
      @Column()
      name: string
    
      // etc...
    
      @OneToMany(() => Address, (address) => address.person)
      addresses: Address[]
    }
    

    business.entity.ts

    export class Business {
      @Column()
      name: string
    
      // etc...
    
      @OneToMany(() => Address, (address) => address.business)
      addresses: Address[]
    }
    

    address.entity.ts

    export class Address {
      @Column()
      name: string
    
      // etc...
    
      @ManyToOne(() => Person, (p) => p.addresses)
      person: Person
    
      @ManyToOne(() => Business , (b) => b.addresses)
      business: Business
    }
    

    如果你坚持在你的地址中没有ManyToOne,你可以通过建立关系ManyToMany来规避这个问题。请记住,这将以更大的查询和更多表的形式产生一些开销。这是因为多对多将创建一个连接表,并且需要一个额外的连接才能从数据库中获取数据。这一切都由 orm 照顾。

    那就是:

    person.entity.ts

    export class Person {
      @Column()
      name: string
    
      // etc...
    
      @ManyToMany(() => Address)
      addresses: Address[]
    }
    

    business.entity.ts

    export class Business {
      @Column()
      name: string
    
      // etc...
    
      @ManyToMany(() => Address)
      addresses: Address[]
    }
    

    address.entity.ts

    export class Address {
      @Column()
      name: string
    
      // etc...
    }
    

    【讨论】:

      【解决方案2】:

      我假设实体 BusinessPerson 之间没有关系。

      目前的数据库设计存在一个问题-

      删除一个人将删除与该特定人关联的所有地址。如果同一个地址(由于删除某人而被删除)与某些业务相关联,这将导致问题。

      我宁愿创建一个单独的链接表BusinessAndPersonAddress,其中businessIdpersonId 作为外键。这样您就可以将同一个地址关联到多个企业和个人。

      在这种情况下,删除人员将仅删除链接表BusinessAndPersonAddress 中与要删除的人员相关联的地址条目,如果地址条目与某些业务相关联,则将保留不受影响。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-01-30
        • 1970-01-01
        • 2017-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多