【问题标题】:TypeORM throws QueryFailedError Table already exists on MySQL when synchronize is true当同步为真时,TypeORM 抛出 QueryFailedError 表已存在于 MySQL
【发布时间】:2020-10-07 14:39:11
【问题描述】:

我正在使用 NestJS、TypeORM 和 MySQL 构建 Web 应用程序。

我正在使用.env 文件来传递一些环境变量以连接到我的本地数据库。同步设置为true

app.module.ts

@Module({
    imports: [
        ConfigModule.forRoot({ envFilePath: '.env' }),
        TypeOrmModule.forRootAsync({
            imports: [ConfigModule],
            useFactory: (configService: ConfigService) => ({
                type: 'mysql',
                host: configService.get('TYPEORM_HOST'),
                port: configService.get('TYPEORM_PORT'),
                username: configService.get('TYPEORM_USERNAME'),
                password: configService.get('TYPEORM_PASSWORD'),
                database: configService.get('TYPEORM_DATABASE'),
                autoLoadEntities: true,
                synchronize: configService.get('TYPEORM_SYNCHRONIZE'),
            }),
            inject: [ConfigService],
        }),
    ],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {
    constructor(private connection: Connection) {}
}

另外,我有一个导入用户实体的用户模块。

users.module.ts

import { User } from './Entities/User.entity';

@Module({
    imports: [TypeOrmModule.forFeature(
        [User]
    )],
    controllers: [UsersController],
    providers: [UsersService],
})
export class UsersModule { }

User.entity.ts

@Entity({ name: "Users"})
export class User {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    userName: string;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    email: string;
}

假设我的数据库是空的,当第一次启动应用程序时,TypeORM 同步会自动为我创建具有适当列和数据类型的用户表。但是,当关闭应用程序并尝试重新启动时,我收到此错误:

[Nest] 14876   - 06/17/2020, 12:37:33 PM   [ExceptionHandler] Table 'users' already exists +3ms
QueryFailedError: Table 'users' already exists
    at new QueryFailedError (C:\MyProject\Server\node_modules\typeorm\error\QueryFailedError.js:11:28)
    at Query.onResult (C:\MyProject\Server\node_modules\typeorm\driver\mysql\MysqlQueryRunner.js:170:45)
    at Query.execute (C:\MyProject\Server\node_modules\mysql2\lib\commands\command.js:30:14)
    at PoolConnection.handlePacket (C:\MyProject\Server\node_modules\mysql2\lib\connection.js:417:32)
    at PacketParser.onPacket C:\MyProject\Server\node_modules\mysql2\lib\connection.js:75:12)
    at PacketParser.executeStart (C:\MyProject\Server\node_modules\mysql2\lib\packet_parser.js:75:16)
    at Socket.<anonymous> (C:\MyProject\Server\node_modules\mysql2\lib\connection.js:82:25)
    at Socket.emit (events.js:315:20)
    at addChunk (_stream_readable.js:302:12)
    at readableAddChunk (_stream_readable.js:278:9)

如果我随后关闭同步并重新启动它,我会收到同样的错误。我唯一的解决方法是删除users 表,重新打开同步以重新创建它,然后将其关闭。 TypeORM 尝试重新创建已经存在的表是否有原因?为了便于使用,我不想每次都记得切换同步。

【问题讨论】:

  • 您找到解决此问题的方法了吗?
  • @Hyra10 不,因为我在发布此问题后不久就转到了另一个问题。如果你弄明白了,请在此处发布答案。
  • 我也遇到了这个问题,但是虽然我也给了我这个例外,但我只是重新启动服务器并成功运行。并且该表也在数据库中创建,并读取以使用。 ???奇怪的东西。

标签: mysql nestjs typeorm


【解决方案1】:

在我的情况下,问题是由

引起的
  synchronize: true
  migrationsRun: true

typeOrmConfig

应该只将 synchronize 或 migrationsRun 设置为 true,而不是同时设置

【讨论】:

  • 我只将同步设置为 true,但仍然出现此错误
【解决方案2】:

我几乎可以向您保证,问题与您的实体名称是否为大写有关,即

@Entity({ name: "Users"})

TypeORM 似乎不喜欢这样,应该使用:

@Entity({ name: "users"})

查看此线程以获取更多信息 https://github.com/typeorm/typeorm/issues/4420

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,但我只是在我的 ormconfig.ts 文件上将 migrationsRun 设置为 false 并且它起作用了。

    synchronize: false,
    migrationsRun: false,
    

    我认为这个问题是由 orm 在我们手动完成迁移时尝试自动运行迁移引起的。

    【讨论】:

    • 你有例子吗?并且在这个文件中有数据库配置连接。这个文件是一个对象数组。
    • 可以确认。 migrationsRun: false 对我也有帮助。在我的情况下,我尝试通过数字海洋水滴上的 pm2 重新启动服务器,并且由于在通过 migrationsRun 设置为 true 之前已经执行了迁移,因此重新启动没有帮助并导致已经存在的错误。现在我已经将标志设置为false,并且将来会手动进行迁移,直到我知道另一种解决方法
    【解决方案4】:

    我遇到了类似的问题,我终于解决了,我发现我首先将同步设置为 false,然后设置为 true,并进行了一些测试,创建/生成的迁移保持同步为真。我还生成了一些迁移但未应用。后来我将同步设置为false,当我尝试应用迁移时,它给了我你提到的错误。我认为未应用的大量生成的迁移给我带来了问题。

    所以,对我来说,解决问题的是,我删除了所有迁移文件,然后重新生成了迁移并应用了该迁移。这样就解决了问题。

    【讨论】:

      【解决方案5】:

      我遇到了完全相同的错误。 我什么都试过了:

      • 将实体/表减少到最少
      • 更改 TypeOrm 选项(同步、autoLoadEntites、实体、迁移运行...)
      • 将 TypeOrm 配置移至 main.ts 或 .json
      • 更新了 MySQL 版本(包括在 MAC 上完全删除)
      • 用新版本的nestJS和TypeOrm重新初始化整个项目

      => 结论:使用 "synchronize":true 当表已经存在时它永远不会起作用。但是对于开发,您确实希望启用该功能...

      => 我已经安装了“mysql2”(参见 package.json),因为“mysql”不适用于我的 MySQL(设置)。我的 mysql 总是出现 AUTHENTICATION ERROR。

      => 解决方案:使用 'mysql'(不是 2)并且 - 如果它不起作用(AUTH ERROR) - 重新安装(或手动配置)MySQL(最新版本)并选择安装期间的旧身份验证方法。

      希望有所帮助(我在任何地方都没有找到此解决方案)。干杯

      【讨论】:

        【解决方案6】:

        我遇到了同样的问题,我尝试了这篇文章中的所有答案,但没有任何效果。

        这是我的实体:

        @Entity()
        export class Photo {
            @PrimaryGeneratedColumn()
            id: number;
        
            @Column({ length: 500 })
            name: string;
        }
        

        这创建了一个名为 photo 的表,其架构为 public

        为我解决的问题实际上是提供表名和架构:

        @Entity({ name: 'photo', schema: 'public' })
        export class Photo {
            @PrimaryGeneratedColumn()
            id: number;
        
            @Column({ length: 500 })
            name: string;
        }
        

        由于某种原因,TypeORM 的 同步 功能在表为大写且未设置架构时会出现问题。设置架构和表名(小写)后,它使用synchronize: true

        【讨论】:

          【解决方案7】:

          已经有一段时间了,但可能的原因可能是您没有添加实体 glob? https://typeorm.io/#/using-ormconfig/using-environment-variables

            entities: '*.entity.ts',
          

          我认为这应该可以解决问题,因为它会创建实体地图。如果不尝试删除表,让它创建它然后再次尝试同步?

          【讨论】:

            【解决方案8】:

            在运行迁移之前重建您的应用 IE 运行 nest buildyarn build 取决于您在 package.json 中设置命令的方式

            【讨论】:

              【解决方案9】:

              就我而言,我只是设置

              @Entity({ name: 'User' })
              export class User {...} 
              

              改为

              @Entity()
              export class User {...}
              

              “哦,魔法”,错误出来了。

              【讨论】:

                【解决方案10】:

                如果所有其他答案都没有帮助,对我来说问题是我复制了一个模型并忘记更改名称!

                愚蠢的错误,但没有两个同名的模型:D

                @Entity({ name: "users"})
                

                【讨论】:

                  【解决方案11】:

                  制作synchronize: false 为我工作。 但是,使用这种方法,它不会再自动创建表了。它假定该表已经存在。

                  【讨论】:

                  • 首先我将同步设置为 false,然后我将其设置为 true 几天并进行了一些编码,然后再次将其设置为 false,现在我创建了迁移并运行它,但说 xyz 关系已经存在.这是预期的吗?为什么?
                  猜你喜欢
                  • 2021-08-14
                  • 2018-08-13
                  • 2021-07-16
                  • 2017-10-20
                  • 2019-02-03
                  • 2020-12-08
                  • 2023-04-02
                  • 2019-12-15
                  • 1970-01-01
                  相关资源
                  最近更新 更多