Search code examples
typeorm

TypeORM @JoinTable() how to specify custom join columns?


this is my sample data model

enter image description here

I have declared the following classes:

@Entity({
  name: 'user'
})
export class User {
  @Column({ type: 'int4' })
  @PrimaryColumn()
  userid: number
    
  @Column({name: 'name', type: 'varchar', length: 30})
  name: string
    
  @Column({name: 'age', type: 'int2'})
  age: number
    
  @ManyToMany(() => Department, (department)=> department.users)
  @JoinTable({
    name: 'department_user'
  })
  departments: Department[]
}

@Entity({ name: 'department' })
export class Department {
    
  @Column({ type: 'int2' })
  @PrimaryColumn()
  departmentid: number
    
  @Column({type: 'varchar', length: 50})
  title: string
    
  @Column({type:'text'})
  notes: string
    
  @ManyToMany(() => User, (user)=> user.departments)
  @JoinTable({ name: 'department_user' })
  users: User[]  
}

whenever I run the app, it creates the departmentDepartmentId & userUserId columns and not utilize the columns in the corresponding join table. How can I tell typeorm to only use the predefined join column in join table?

Update 2 (as mentioned by @suvantorw)

I recreated the join table with the statement below:

create table department_user(
departmentid integer not null, 
userid integer not null);

alter table department_user add constraint fk_dept_dept foreign key (departmentid) references department(departmentid);
alter table department_user add constraint fk_dept_user foreign key (userid) references "user"(userid);
alter table department_user add constraint pk_dept_user primary key (departmentid, userid);

and modified the entities like this:

user

  @ManyToMany(() => Department, (department)=> department.users)
  @JoinTable({ 
    name: 'department_user',
    joinColumn: { name: 'userid' },
    inverseJoinColumn: { name: 'departmentid' }
  })
  departments: Department[]
}

department

  @ManyToMany(() => User, (user)=> user.departments)
  @JoinTable({
    name: 'department_user',
    joinColumn: { name: 'departmentid' },
    inverseJoinColumn: { referencedColumnName: 'userid' }
  })
  users: User[]  
}

it does run without errors but when it runs the table structure is modified to this modified table structure

As you can see, ,y foreign key constraints are gone and new ones are created. Any clue what I'm doing wrong here?

Update 3

Finally I modified the classes as below and now the TypeORM accepts the relationships and does not create its own. it was a very painful experience to solve this and documentation about this decorator doesn't say much either.

user

  @ManyToMany(() => Department, (department)=> department.users)
  @JoinTable({ 
    name: 'department_user',
    joinColumn: {
      name: 'userid',
      foreignKeyConstraintName: 'fk_dept_user'
    },
    inverseJoinColumn: {
      referencedColumnName: 'departmentid',
      name: 'departmentid',
      foreignKeyConstraintName: 'fk_dept_dept'
    }
  })
  departments: Department[]
}

department

@ManyToMany(() => User, (user)=> user.departments)
  @JoinTable({
    name: 'department_user',
    joinColumn: {
      name: 'departmentid',
      foreignKeyConstraintName: 'fk_dept_dept'
    },
    inverseJoinColumn: {
      referencedColumnName: 'userid',
      name: 'userid',
      foreignKeyConstraintName: 'fk_dept_user'
    }
  })
  users: User[]  
}

Solution

  • You can specify the join column name and inverse join column name. Something like this should work for you:

    @ManyToMany(() => Department, (department)=> department.users)
    @JoinTable({ 
        name: 'department_user',
        joinColumn: { name: 'userid' },
        inverseJoinColumn: { name: 'departmentid' }
    })
    departments: Department[]