typescript TypeORM给了我一个关于列中的空值违反了非空约束的错误;我做错了什么?

g6ll5ycj  于 2022-12-19  发布在  TypeScript
关注(0)|答案(1)|浏览(172)

我正在使用TypeORM来尝试创建一个任务,该任务具有其所属委员会、其相关委员会、其项目负责人和雇员条目的关联条目。
我希望看到一个通过的单元测试可以毫无怨言地执行这一行:

const taskDetails: TaskDetails = {
            title: "Baz Creation",
            startDate: new Date(),
            endDate: new Date(),
            committeeId: newCommittee1.committeeId,
        };
        const taskPayload1 = {
            committees: [newCommittee1, newCommittee2],
            projectLead: newUser1,
            membersToAdd: [newUser1, newUser2, newUser3],
        };
        await taskDAO.createTask(newCommittee1, taskDetails, taskPayload1.committees, taskPayload1.projectLead, taskPayload1.membersToAdd);

但是我得到了以下错误:

QueryFailedError: null value in column "memberUserId" of relation "tasks_for_member" violates not-null constraint

      at PostgresQueryRunner.query (src/driver/postgres/PostgresQueryRunner.ts:299:19)
      at InsertQueryBuilder.execute (src/query-builder/InsertQueryBuilder.ts:163:33)
      at SubjectExecutor.executeInsertOperations (src/persistence/SubjectExecutor.ts:428:42)
      at SubjectExecutor.execute (src/persistence/SubjectExecutor.ts:137:9)
      at EntityPersistExecutor.execute (src/persistence/EntityPersistExecutor.ts:197:21)
      at TaskDAO.createTask (src/db/dao/task.dao.ts:49:13)
      at Object.<anonymous> (tests/dbUtil/purgeDb.test.ts:132:9)

它显然是在说“你知道这个连接表应该有一个条目,对吗?”但不知何故,我没有告诉TypeORM正确地创建那个条目。
但我不明白:
(a)TypeORM应该为我在连接表中创建条目。(b)我将我的数据库中的每个关系都设置为可空。
以下是我的相关任务和成员实体:
Task.ts

@Entity()
export class Task {
    @PrimaryGeneratedColumn()
    taskId: number;

    @Column({ nullable: true })
    description: string;

    @Column({ nullable: true })
    status: Role;

    @ManyToMany(() => Member, (member: Member) => member.tasks, { nullable: true, onDelete: "CASCADE" })
    @JoinTable({ name: "task_leads" })
    leads?: Member[]; // this might be the source of the issue

    @ManyToMany(() => Member, (member: Member) => member.tasks, { nullable: true, onDelete: "CASCADE" })
    @JoinTable({ name: "task_members" })
    members?: Member[]; // this might be the source of the issue

    @ManyToOne(() => Committee, committee => committee.inChargeOf, { nullable: true })
    @JoinColumn({ name: "owning_committee" }) // tried adding this; didnt help
    ownedBy?: Committee;

    @ManyToMany(() => Committee, committee => committee.tasks, { nullable: true, onDelete: "CASCADE" })
    @JoinTable({ name: "task_committees" })
    relatedCommittees?: Committee[];
}

Member.ts:

@Entity()
export class Member {
    @PrimaryGeneratedColumn()
    userId: number;

    @Column({ nullable: true })
    displayName?: string;

    @ManyToMany(() => Committee, committee => committee.members, { nullable: true, onDelete: "CASCADE" })
    @JoinTable({ name: "member_of" })
    memberOf?: Committee[];

    @ManyToMany(() => Committee, committee => committee.leads, { nullable: true, onDelete: "CASCADE" })
    @JoinTable({ name: "lead_of" })
    leadOf?: Committee[];

    @OneToMany(() => Committee, committee => committee.head, { nullable: true, onDelete: "CASCADE" })
    headOf?: Committee;

    @ManyToMany(() => Task, (task: Task) => task.members, { nullable: true, onDelete: "CASCADE" })
    @JoinTable({ name: "tasks_for_member" }) // this might be the source of the issue
    tasks?: Task[];
}

下面是我创建任务的方法:

public async createTask(
        headCommittee: Committee,
        taskDetails: TaskDetails,
        relatedCommittees: Committee[] | null,
        projectLead: Member | null,
        membersToAdd: Member[] | null,
    ): Promise<Task> {
        try {
            const task = new Task();
            task.title = taskDetails.title;
            task.startDate = taskDetails.startDate;
            task.endDate = taskDetails.endDate;
            task.ownedBy = headCommittee;
            if (projectLead) {
                task.leads = [projectLead];
            }
            if (membersToAdd) {
                task.members = membersToAdd;
                // // QueryFailedError: null value in column "memberUserId" of relation "tasks_for_member" violates not-null constraint
                for (const member of membersToAdd) { // this loop didn't help me
                    member.tasks = [task];
                    this.memberRepository.save(member);
                } 
            }
            if (relatedCommittees) {
                task.relatedCommittees = relatedCommittees;
            }
            console.log(task, "36rm");
            await this.taskRepository.save(task);
            return task;
        } catch (error: unknown) {
            // handle
        }
    }

我真的希望task.members = membersToAdd;行能帮我处理这个问题,因为它是TypeScript,所以函数的所有参数都是他们说的那样,我不明白。
编辑:为了简洁起见,我删除了成员和任务表中的一些列。2任务dao方法显示了任务真正拥有的字段。
edit 2:注解掉这个错误会消失,但是我需要这个块来工作!

if (membersToAdd) {
         task.members = membersToAdd;
     }

edit 3:我在一个单独的项目中重新创建了“相关”代码,并且,正如我所展示的,这些代码在那里工作!因此,我未能在我发布的代码中发现问题的实际来源。
edit 4:找到了错误的来源,虽然我不明白如何
在我的server.ts文件中

import {
    committeeRepository,
    taskRepository,
    memberRepository,
} from "./db/data-source";
// later...
const committeeDAO = new CommitteeDAO(committeeRepository);
const memberDAO = new MemberDAO(memberRepository); // commenting out this & the prior line fixes the bug!
const taskDAO = new TaskDAO(taskRepository, memberDAO, memberRepository);

它们从data-source.ts导出,如下所示:

export const AppDataSource = new DataSource({
    type: "postgres",
    host: "localhost",
    port: 5432,
    username: "postgres",
    password: "postgres",
    database: "typeormtest",
    synchronize: true,
    logging: false,
    entities: [Member, Task, Committee ],
    subscribers: [],
    migrations: [],
});

export const committeeRepository = AppDataSource.getRepository(Committee);
export const memberRepository = AppDataSource.getRepository(Member);
export const taskRepository = AppDataSource.getRepository(Task);

在我的测试的顶部我做类似的:

const memberDAO = new MemberDAO(memberRepository);
const taskDAO = new TaskDAO(taskRepository, memberDAO, memberRepository);
const committeeDAO = new CommitteeDAO(committeeRepository)

我真的不明白,为什么这句话会引起bug?

kzmpq1sx

kzmpq1sx1#

我想通了。
我在任务〈=〉委员会和任务〈=〉成员的关系两端都标记了@JoinTable
事实上,它只应该出现在,我想,那一面,嗯,我不知道该怎么说,check the docs here

@Entity()
export class Album {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    name: string

    @ManyToMany(() => Photo, (photo) => photo.albums)
    @JoinTable() // look here
    photos: Photo[]
}

export class Photo {
    // ... other columns

    @ManyToMany(() => Album, (album) => album.photos)
    albums: Album[] // and here -- @JoinTable is NOT present
}
const photo = new Photo()
photo.name = "Me and Bears"
photo.description = "I am near polar bears"
photo.filename = "photo-with-bears.jpg"
photo.views = 1
photo.isPublished = true
photo.albums = [album1, album2] // and look here - it gets the albums
await AppDataSource.manager.save(photo)

Photo获得JoinTable,因为相册将附加到JoinTable。如果照片将附加到album.photos = [photo1, photo2]之类的相册,则@JoinTable将位于另一侧

相关问题