typeorm
typeorm copied to clipboard
column "x" specified more than once
Issue Description
I get an error while saving over an embedded object. It holds both the user and its related user id. For example;
@ManyToOne(() => User)
@JoinColumn({ name: 'created_by' })
createdBy: User;
@Column({ name: "created_by", nullable: true })
createdById: number;
When I want to save data, the created_by and updated_by fields are duplicates trying to save to the db. As seen below, the created_by and updated_by fields are duplicated.
'INSERT INTO "role"("name", "type", "description", "created_by", "updated_by", "created_at", "updated_at", "deleted_at", "created_by", "updated_by", "created_host", "updated_host") VALUES ($1, DEFAULT, $2, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, DEFAULT, $3, $4) RETURNING "id", "created_at", "updated_at", "deleted_at"'
As a result, I get the following error.
'column "created_by" specified more than once'
These are my entities :
//base entity
export abstract class EntityBase extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
}
//embedded entity
export class CuBy {
@ManyToOne(() => User)
@JoinColumn({ name: 'created_by' })
createdBy: User;
@ManyToOne(() => User)
@JoinColumn({ name: 'updated_by' })
updatedBy: User;
@Column({ name: "created_by", nullable: true })
createdById: number;
@Column({ name: "updated_by", nullable: true })
updatedById: number;
static new(): CuBy {
const currentUser = HttpContext.currentUser();
const cu = new CuBy();
cu.createdBy = new User();
cu.updatedBy = new User();
cu.createdBy.id = currentUser.id;
cu.updatedBy.id = currentUser.id;
return cu;
}
}
export enum RoleType {
SUPER_ADMIN = 10,
ADMIN = 15,
MODERATOR = 20,
SUPER_MODERATOR = 25
}
@Entity("role")
@Unique("index_type", ["type"])
export class Role extends EntityBase {
@IsString({ always: true })
@Column({ unique: true, length: 50 })
name: string
@Column({ name: "type", type: "enum", enum: RoleType, nullable: true })
type: RoleType
@IsOptional({ always: true })
@IsString({ always: true })
@Column({ nullable: true, length: 256 })
description: string
@Column(() => CuBy, { prefix: false })
userBy: CuBy
static async with(name: string, description: string) {
const role = new Role();
role .name = name;
role .description = description;
await role.save();
}
}
@EventSubscriber()
export class EverythingSubscriber implements EntitySubscriberInterface {
constructor(connection: Connection) {
connection.subscribers.push(this);
}
beforeInsert(event: InsertEvent<any>) {
event.metadata.embeddeds.forEach(t=>{
if(t.type.name === CuBy.name){
event.entity["userBy"] = CuBy.new();
}
})
}
}
Any idea how to solve this?
My Environment
Dependency | Version |
---|---|
Operating System | |
Node.js version | v12.3.0 |
Typescript version | v3.7.5 |
TypeORM version | v0.2.29 |
Additional Context
Relevant Database Driver(s)
- [ ]
aurora-data-api
- [ ]
aurora-data-api-pg
- [ ]
better-sqlite3
- [ ]
cockroachdb
- [ ]
cordova
- [ ]
expo
- [ ]
mongodb
- [ ]
mysql
- [ ]
nativescript
- [ ]
oracle
- [x]
postgres
- [ ]
react-native
- [ ]
sap
- [ ]
sqlite
- [ ]
sqlite-abstract
- [ ]
sqljs
- [ ]
sqlserver
Are you willing to resolve this issue by submitting a Pull Request?
- [ ] Yes, I have the time, and I know how to start.
- [ ] Yes, I have the time, but I don't know how to start. I would need guidance.
- [ ] No, I don't have the time, although I believe I could do it if I had the time...
- [ ] No, I don't have the time and I wouldn't even know how to start.
I believe you don't need to (and in this case shouldn't) use @JoinColumn
if you have manually defined the createdById
column. The matching between relation and relation id column is based on the property name rather than the database name, so the custom column name shouldn't make a difference either.
@nebkat hi, I established this relationship by following here. I guess there is a problem with embedded objects. If I move the fields on the embedded object to the role entity, there is no problem.
@Entity("role")
@Unique("index_type", ["type"])
export class Role extends EntityBase {
@IsString({ always: true })
@Column({ unique: true, length: 50 })
name: string
@Column({ name: "type", type: "enum", enum: RoleType, nullable: true })
type: RoleType
@IsOptional({ always: true })
@IsString({ always: true })
@Column({ nullable: true, length: 256 })
description: string
@ManyToOne(() => User)
@JoinColumn({ name: 'created_by' })
createdBy: User;
@ManyToOne(() => User)
@JoinColumn({ name: 'updated_by' })
updatedBy: User;
@Column({ name: "created_by", nullable: true })
createdById: number;
@Column({ name: "updated_by", nullable: true })
updatedById: number;
static async with(name: string, description: string) {
const currentUser = HttpContext.currentUser();
const role = new Role();
role .name = name;
role .description = description;
roleEntity.createdBy = new User();
roleEntity.updatedBy = new User();
roleEntity.createdBy.id = currentUser.id;
roleEntity.updatedBy.id = currentUser.id;
await role.save();
}
}
i have the same issue. @melihorhan do you find a way to solve this?
i have the same issue. @melihorhan do you find a way to solve this?
@yusef-ho Unfortunately I couldn't solve this problem. The contributors needs to review it.
Is there any solution to this issue?
TBH it's unlikely there is an issue, because we have similar use cases and they are test-covered. But you can create a PR with a minimal reproduction failing test and I'll check it.
If one uses Single Table Inheritance and tries to reference columns in both the parent and child table models using the @Column
decorator, one will get his error as well...
Also getting this issue. Seems to happen when the column name doesn't use camel case.
I solved the problem by using the method upstairs. you use 'created_by' to join table , and the same cloumn in the entity cause the issue, you delete the '@Column' above the cloumn, then you can use the cloumn to query or display but do not need to assignment.
any updates?
any updates on this? I'm running into the same issue.