【问题标题】:Postgres enum in TypeORMTypeORM 中的 Postgres 枚举
【发布时间】:2017-12-11 23:27:17
【问题描述】:

在 TypeORM 中,如何创建一个 postgres 枚举类型 Gender 就像在这个原始查询中一样

CREATE TYPE public.Gender AS ENUM (
    'male', 'female'
);
ALTER TABLE public.person ALTER COLUMN gender TYPE public.gender USING gender::gender;

并在 Entity 类中使​​用它?

我试过了

@Entity()
export class Person {
    @Column('enum')
    gender: 'male' | 'female'
}

但显然这不是正确的方法,因为我收到错误消息“类型 enum 不存在”。

我也不想使用 typescript 枚举,因为它会在数据库中给我一堆 0 和 1。

【问题讨论】:

    标签: postgresql typeorm


    【解决方案1】:

    编辑:这个答案仍然有效,但有点过时,因为0.1.0 alpha 版本的 TypeORM 支持 PostgreSQL 和 MySQL 的枚举。


    PostgreSQL 有一个内置的枚举类型,但不幸的是TypeORM 目前是only supports it for MySQL

    但是,您可以通过将 @Column 类型用作 int 并将枚举用于您的字段类型,使用 int 类型枚举实现类似的结果。

    enum Gender {
      Male,
      Female,
      Other
    }
    
    @Entity()
    export class Person {
        @Column('int')
        gender: Gender
    }
    

    (此方法允许您在需要时使用@IsEnum decorator from class-validator 来验证输入)

    您也可以使用字符串枚举(TypeScript 2.4 上可用,请查看 Typescript `enum` from JSON string 以获得旧版本),如果是这种情况,只需将数据类型更改为 string

    enum Gender {
      Male = 'male',
      Female = 'female',
      Other = 'other'
    }
    
    @Entity()
    export class Person {
        @Column('text')
        gender: Gender
    }
    

    【讨论】:

      【解决方案2】:

      正如接受的答案所述,它现在在 postgres 中得到支持,但仍然存在错误:Github issue,修复可能会在下一个 RC 中发布。同时,我在线程上看到了一个不错的解决方案,我什至喜欢它而不是实际功能完全正常工作:

      fwiw 我一直在使用带有检查约束的字符串枚举。很多 比创建全新数据的实际 postgres 枚举更灵活 postgres 索引中的类型并且真的很难管理(更改表, 等等)

      export function CheckEnum(tableName: string, fieldName: string, enumValue: any) {
        // Hash enum value and put it as part of constraint name so we can
        // force typeorm to generate migration for enum changes.
        const hash = crypto
          .createHash('sha1')
          .update(Object.values(enumValue).join(''))
          .digest('hex')
        return Check(
          // https://til.hashrocket.com/posts/8f87c65a0a-postgresqls-max-identifier-length-is-63-bytes
          `cke_${tableName}_${fieldName}_${hash}`.slice(0, 63),
          `${fieldName} in (${Object.values(enumValue).map(t => `'${t}'`)})`,
        )
      }
      

      然后像这样使用它

      export enum Gender {
        Male = 'male',
        Female = 'female',
        Other = 'other'
      }
      
      @Entity()
      @CheckEnum('person', 'gender', Gender)
      export class Person {
      

      【讨论】:

        【解决方案3】:

        对于 Postgres,列类型应该是“文本”,而不是“字符串”,因为字符串会导致 DataTypeNotSupportedError:“postgres”数据库不支持“”中的数据类型“string”。

        【讨论】:

          【解决方案4】:

          TypeOrm 现在支持 Enum for postgres

          docs

          postgres 和 mysql 支持枚举列类型。有多种可能的列定义:

          使用打字稿枚举:

          export enum UserRole {
              ADMIN = "admin",
              EDITOR = "editor",
              GHOST = "ghost"
          }
          
          @Entity()
          export class User {
          
              @PrimaryGeneratedColumn()
              id: number;
          
              @Column({
                  type: "enum",
                  enum: UserRole,
                  default: UserRole.GHOST
              })
              role: UserRole;
          
          }
          
          

          使用带有枚举值的数组:

          export type UserRoleType = "admin" | "editor" | "ghost",
          
          @Entity()
          export class User {
          
              @PrimaryGeneratedColumn()
              id: number;
          
              @Column({
                  type: "enum",
                  enum: ["admin", "editor", "ghost"],
                  default: "ghost"
              })
              role: UserRoleType;
          }
          

          【讨论】:

            【解决方案5】:

            请参阅@noam steiner 的回答,但 TypeORM 会识别枚举类型而不明确提供它,所以这就足够了:

            enum SomeEnum{
              # ...
            }
            
            class Entity {
              @Field()
              @Column()
              someEnumField: SomeEnum;
            }
            

            【讨论】:

              【解决方案6】:

              值得一提的是,在多个实体中使用相同的枚举可能会导致奇怪的枚举缺失属性错误。我花了几个小时才弄清楚这个问题。

              【讨论】:

                猜你喜欢
                • 2023-04-01
                • 2023-04-04
                • 1970-01-01
                • 2018-03-12
                • 2021-08-31
                • 2017-02-01
                • 2022-01-21
                • 1970-01-01
                • 2018-12-30
                相关资源
                最近更新 更多