Search code examples
typescripttypeormtypeorm-activerecord

TypeORM: OneToOne with OneToMany on same Entity


I have 2 entities that I want related to each other in 2 ways. I'm going to represent this as a Class and Students. I want all Students to belong to one Class but I want the Class to not only have many Students, but also a class president. The entities look like this right now:

@Entity()
export class Class extends BaseEntity {
  @PrimaryGeneratedColumn("uuid")
  id: string

  @OneToOne(type => Student, { nullable: true })
  @JoinColumn({ name: "classPresident", referencedColumnName: "id" })
  classPresident?: Student

  @OneToMany(type => Student, (student) => student.class, { nullable: true })
  students?: Student[]
}

@Entity()
export class Student extends BaseEntity {
  @PrimaryGeneratedColumn("uuid")
  id: string

  @ManyToOne(() => Class, (c) => c.students)
  class?: Class
}

This isn't working how I would expect. I would expect the Class table to be created with column classPresident that is a key to a Student. I'm hoping to not have to do the keys myself, any criticism is welcome.


Solution

  • I would expect the Class table to be created with column classPresident that is a key to a Student.

    I can not reproduce your problem. What you expect is exactly what is happening when I use your entities.

    Here is what typeorm logs:

    query: CREATE TABLE "class" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "classPresident" uuid, CONSTRAINT "REL_ba4e89afdc05df2bda1c2c532c" UNIQUE ("classPresident"), CONSTRAINT "PK_0b9024d21bdfba8b1bd1c300eae" PRIMARY KEY ("id"))
    creating a new table: public.student
    query: CREATE TABLE "student" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "classId" uuid, CONSTRAINT "PK_3d8016e1cb58429474a3c041904" PRIMARY KEY ("id"))
    creating a foreign keys: FK_ba4e89afdc05df2bda1c2c532c2 on table "class"
    query: ALTER TABLE "class" ADD CONSTRAINT "FK_ba4e89afdc05df2bda1c2c532c2" FOREIGN KEY ("classPresident") REFERENCES "student"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
    creating a foreign keys: FK_bd5c8f2ef67394162384a484ba1 on table "student"
    query: ALTER TABLE "student" ADD CONSTRAINT "FK_bd5c8f2ef67394162384a484ba1" FOREIGN KEY ("classId") REFERENCES "class"("id") ON DELETE NO ACTION ON UPDATE NO ACTION
    

    Here is a screenshot of the structure created: Structure of table class

    EDIT: My package.json:

    {
       "name": "typeorm-nodejs-demo",
       "version": "0.0.1",
       "description": "Awesome project developed with TypeORM.",
       "type": "commonjs",
       "devDependencies": {
          "@types/node": "^16.11.10",
          "ts-node": "10.7.0",
          "typescript": "4.5.2"
       },
       "dependencies": {
          "dotenv": "^16.0.1",
          "pg": "^8.4.0",
          "reflect-metadata": "^0.1.13",
          "typeorm": "0.3.7"
       },
       "scripts": {
          "start": "ts-node src/index.ts",
          "typeorm": "typeorm-ts-node-commonjs"
       }
    }
    

    My tsconfig.json:

    {
       "compilerOptions": {
          "lib": [
             "es5",
             "es6"
          ],
          "target": "es2020",
          "module": "commonjs",
          "moduleResolution": "node",
          "outDir": "./build",
          "emitDecoratorMetadata": true,
          "experimentalDecorators": true,
          "sourceMap": true
       }
    }
    

    To work with extends BaseEntity I had to split each entity to its own file.