I have a Typescript Nestjs project using TypeORM and a PostgreSQL database, and I have trouble defining many-to-one relationships, because TypeORM tries to create an ID field of type integer, whereas I'm using UUID fields. Is there a way to tell TypeORM to use a different data-type than integer?
Here's an example of an entity that's not working:
export class AgentKitsEntity implements Model {
@PrimaryGeneratedColumn()
@Generated('uuid')
id: string;
}
@Entity({name: 'users'})
export class User extends AgentKitsEntity implements UserModel {
@Column()
username: string;
@ManyToOne(type => View)
@JoinColumn({name: 'view_id', referencedColumnName: 'id'})
view: View;
}
This leads to the following error:
query failed: ALTER TABLE "users" ADD CONSTRAINT "FK_2ed8b186dce83a446f94ac9aae4" FOREIGN KEY ("view_id") REFERENCES "views"("id")
error: { error: foreign key constraint "FK_2ed8b186dce83a446f94ac9aae4" cannot be implemented
at Connection.parseE (/home/jonathan/projects/agent-kits/api-data/node_modules/pg/lib/connection.js:554:11)
at Connection.parseMessage (/home/jonathan/projects/agent-kits/api-data/node_modules/pg/lib/connection.js:379:19)
at Socket.<anonymous> (/home/jonathan/projects/agent-kits/api-data/node_modules/pg/lib/connection.js:119:22)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:601:20)
name: 'error',
length: 228,
severity: 'ERROR',
code: '42804',
detail: 'Key columns "view_id" and "id" are of incompatible types: integer and uuid.',
hint: undefined,
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'tablecmds.c',
line: '6503',
routine: 'ATAddForeignKeyConstraint' }
EDIT: Just to be clear, the issue isn't creating the UUID field for the primary key, that's working. The issue is that the table I'm referencing (in this example, "views"), uses a UUID primary key, so I need to use a UUID for the field referencing it as well ("views", in this example). TypeORM automatically creates the "view_id" field with an integer type, presumably because it assumes that primary key values will (should?) always be integers (which strikes me as a pretty crazy assumption).
It must be configurable somehow, no?
I ended up finding the solution to this, and I'll post it here for future reference.
The following works for me:
export class AgentKitsEntity implements Model {
@PrimaryGeneratedColumn('uuid')
@Generated('uuid')
id: string;
}
@Entity({name: 'users'})
export class User extends AgentKitsEntity implements UserModel {
@Column()
username: string;
@ManyToOne(type => View, { nullable: true })
@JoinColumn({name: 'view_id'})
view: View;
}
The key difference that seems to have solved it is that I specified 'uuid' in the @PrimaryGeneratedColumn()
decorator. This is surprising, as the fields actually were correctly created as UUID in the database, but it seems as though TypeORM assumes the key fields are integers unless you explicitly specify the type, even though it knows enough to figure out how to create the right data type for the field itself.
EDIT: On closer examination, it turns out that the @Generated('uuid') entity is redundant, and so the code for the base class above can be simplified to:
export class AgentKitsEntity implements Model {
@PrimaryGeneratedColumn('uuid')
id: string;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With