sfarzoso
sfarzoso

Reputation: 1600

Cannot create a OneToOne relationship

I'm using Typeorm and I'm trying to create a OneToOne relationship between two entities: Project and Resource. For doing so I did:

import { Entity, Column, PrimaryGeneratedColumn, OneToMany, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
import { Customer } from './customer';

@Entity()
export class Project {
    @PrimaryGeneratedColumn()
    public id!: number;

    @Column({ nullable: false })
    public name!: string;

    @Column({ nullable: true })
    public description!: string;
    
    @PrimaryColumn({ nullable: false })
    public customer_id!: number;

    @OneToOne(() => Customer)
    @JoinColumn({ name: 'customer_id' })
    public customer!: Customer;

    @Column({ default: false })
    public deleted: boolean = false;
}

then I have Resource entity:

import { Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm';
import { Project } from './project';

@Entity()
export class Resource {
    @PrimaryGeneratedColumn()
    public id!: number;

    @Column({ nullable: false })
    public name!: string;

    @Column()
    public description: string = "";

    @Column()
    public deleted: boolean = false;

    @PrimaryColumn({ nullable: false })
    public project_id!: number;

    @OneToOne(() => Project)
    @JoinColumn({ name: 'project_id' })
    public project!: Project;
}

Essentially a Resource can be associated to one Project, so I've defined the OneToOne decorator above the project property of Resource, and then, I've also defined a column called project_id, I need this columns for my API design.

Usually Typeorm create the projectId column, so I've specified with name property: project_id, the problem's that I got:

message: "ER_DUP_FIELDNAME: Duplicate column name 'project_id'", code: 'ER_DUP_FIELDNAME', errno: 1060, sqlMessage: "Duplicate column name 'project_id'", sqlState: '42S21', index: 0, sql: 'CREATE UNIQUE INDEX REL_1c2e17cbbe9905b63f1f870679 ON resource (project_id, project_id)', name: 'QueryFailedError', query: 'CREATE UNIQUE INDEX REL_1c2e17cbbe9905b63f1f870679 ON resource (project_id, project_id)', parameters: [] }

I was able to fix this using:

@JoinColumn({ name: 'project_id', referencedColumnName: 'id' })

but I don't understand why in the first setup this didn't worked 'cause I did exactly the same for Project entity, in particular linking the Customer table and it works.

Also, I'm not sure that this is correct, these are the constraints created:

enter image description here

and this is the ER so far:

enter image description here

Upvotes: 0

Views: 1093

Answers (1)

Carlo Corradini
Carlo Corradini

Reputation: 3425

It didn't worked because you have a field named project_id (the @PrimaryColumn) and another field named project with the name option set to project_id. So as you can see TypeORM is trying to create two fields with the same name. This is the origin of the error.

You can remove the field public project_id!: number; since TypeORM loads the relation project!: Project; automatically (only the id or the entire entity if you want) so it's useless.

If you really want the relation id then use the @RelationId decorator.

Example below:

import { Entity, Column, PrimaryGeneratedColumn, OneToOne, JoinColumn, PrimaryColumn, RelationId } from 'typeorm';
import { Project } from './project';

@Entity()
export class Resource {
    @PrimaryGeneratedColumn()
    public id!: number;

    @Column({ nullable: false })
    public name!: string;

    @Column()
    public description: string = "";

    @Column()
    public deleted: boolean = false;

    // CHANGES HERE
    @RelationId((resource: Resource) => resource.project)
    public project_id!: number;

    @OneToOne(() => Project)
    @JoinColumn()
    public project!: Project;
}

Hope it helps :)

Upvotes: 2

Related Questions