在保存实体 PrimaryGeneratedColumn 值未生成时,给出 NOT NULL 约束错误

Posted

技术标签:

【中文标题】在保存实体 PrimaryGeneratedColumn 值未生成时,给出 NOT NULL 约束错误【英文标题】:On saving entity PrimaryGeneratedColumn value not generated, gives NOT NULL constraint error 【发布时间】:2019-03-27 15:47:56 【问题描述】:

Typeorm 0.2.8

我正在为移动设备和浏览器 (PWA) 使用构建一个 Ionic 应用程序。下面是我项目中的一些缩短代码。我用PrimaryGeneratedColumn 创建了一个简单的实体并尝试插入一个实例。这会生成有关主列为NULL 的错误。 “生成”这个词不是意味着生成了列值吗?

这是一个错误吗? sqljs 驱动程序特有的东西?还是我错过了一些明显而简单的东西?

实体

@Entity()
export class MyEntity 

    @PrimaryGeneratedColumn()
    id:number;

    @Column()
    name:string;

    @CreateDateColumn()
    createdAt:string;

迁移

export class Migration20181022133900 implements MigrationInterface 

    async up(queryRunner: QueryRunner): Promise<any> 
        await queryRunner.createTable(new Table(
            name: 'my_entity',
            columns: [
                
                    name: 'id',
                    type: 'int',
                    isPrimary: true,
                    isGenerated: true
                ,
                
                    name: 'name',
                    type: 'varchar'
                ,
                
                    name: 'createdAt',
                    type: 'timestamp',
                    'default': 'now()'
                
            ]
        ), true);
    

    async down(queryRunner: QueryRunner): Promise<any> 
        await queryRunner.dropTable('my_entity');
    

数据库提供者

const DATABASE_SHARED_OPTIONS:Partial<ConnectionOptions> = 
    entities: [
        MyEntity
    ],
    logging: 'all',
    logger: new DatabaseLogger(),
    migrationsRun: true,
    migrations: [
        Migration20181022133900
    ]
;
@Injectable()
export class Database 

    constructor(public platform:Platform) 

    setup(): Promise<Connection> 
        let options: CordovaConnectionOptions | SqljsConnectionOptions;

        // Mobile app
        if (this.platform.is('cordova')) 
            options = 
                type: 'cordova',
                database: 'my_project.db',
                location: 'default',
            ;
            options = Object.assign(options, DATABASE_SHARED_OPTIONS);
        

        // Browser PWA app
        else 
            options = 
                type: 'sqljs',
                autoSave: true,
                location: 'my_project',
            ;
            options = Object.assign(options, DATABASE_SHARED_OPTIONS);
        

        return createConnection(options);
    

应用组件

export class MyApp 

    constructor(
        platform: Platform,
        database: Database
    ) 
      platform.ready().then(() => 
        database.setup()
            .then((connection) => 
                  this.insertTest();
            );
      );
    

    insertTest() 
        const myEntity= new MyEntity();
        myEntity.name = 'foo';
        getRepository(MyEntity).save(myEntity)
            .then((data) => 
                  console.log(data); // never reached due to error
            );
    

数据库日志显示以下查询(带参数["foo"]):

INSERT INTO "my_entity"("name", "createdAt") VALUES (?, datetime('now'))

以下错误显示在我的控制台中:

ERROR Error: Uncaught (in promise): QueryFailedError: NOT NULL constraint failed: my_entity.id

更新 1

它似乎只在使用迁移时给出错误。删除迁移并在数据库设置上使用synchronize: true 可以工作并为实体生成id。那么我在迁移代码中的列定义有问题吗?


    name: 'id',
    type: 'int',
    isPrimary: true,
    isGenerated: true

更新 2

好的,我修好了。 @PrimaryGeneratedColumn 的迁移配置似乎非常具体。对于其他面临此问题的人,这为我解决了问题:


    name: 'id',
    type: 'integer', // instead of 'int', required for the increment strategy
    isPrimary: true,
    isGenerated: true,
    generationStrategy: 'increment' // thought this was the default

【问题讨论】:

【参考方案1】:

好的,我修好了。 @PrimaryGeneratedColumn 的迁移配置似乎非常具体。对于其他面临此问题的人,这为我解决了问题:


    name: 'id',
    type: 'integer', // instead of 'int', required for the increment strategy
    isPrimary: true,
    isGenerated: true,
    generationStrategy: 'increment' // thought this was the default

【讨论】:

以上是关于在保存实体 PrimaryGeneratedColumn 值未生成时,给出 NOT NULL 约束错误的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止实体框架尝试保存/插入子对象?

在 coredata 中保存实体数组

保存已编辑的核心数据实体未保存

如何在restkit映射后和保存到实体之前清除旧实体?

“保存”方法是不是属于业务域实体?

如何仅保存/更新父实体而不将其子实体保存在 asp.net mvc 的 EF6 中?