I have the following entities:
@Entity()
@TableInheritance({ column: { name: 'type', type: 'varchar' } })
export class Order extends BaseEntity {
@PrimaryColumn({ length: 21 })
public id: string;
@OneToMany(() => OrderedItem, (item) => item.order, { cascade: true })
items: OrderedItem[];
...
@BeforeInsert()
generateId() {
if (!this.id) {
this.id = nanoid();
}
}
}
@ChildEntity()
export class TenantOrder extends Order {
...
}
@Entity()
export class OrderedItem BaseEntity {
@PrimaryColumn({ length: 21 })
public id: string;
@Index()
@ManyToOne(() => Order, (order) => order.items)
order: Order[];
...
@BeforeInsert()
generateId() {
if (!this.id) {
this.id = nanoid();
}
}
}
I use nanoid to autogenerate IDs for entities if they are not set. The problem is the repository tries to save embedded entites (OrderedItem) first while TenantOrder is not saved yet, so I get an error. For example:
This works correctly:
const order = new Order();
const item1 = new OrderedItem();
...
order.items = [item1, ...];
await orderRepository.save(order); // This works
This fails:
const order = new TenantOrder();
const item1 = new OrderedItem();
...
order.items = [item1, ...];
await tenantOrderRepository.save(order); // This doesn't work
Error: (Repoisitory should save Order first but it thinksk, it is already a saved entity.)
query: START TRANSACTION
query: INSERT INTO `ordered_payable_item`(`id`, `quantity`, `itemId`, `orderId`) VALUES (?, ?, ?, ?) -- PARAMETERS: ["my6IV1RSu2Srlqc1Dz66n",2,"D2wPuI6qPf4A4r-2EjM79","acuJ1QdQ9FayosNNlJrCw"]
query failed: INSERT INTO `ordered_payable_item`(`id`, `quantity`, `itemId`, `orderId`) VALUES (?, ?, ?, ?) -- PARAMETERS: ["my6IV1RSu2Srlqc1Dz66n",2,"D2wPuI6qPf4A4r-2EjM79","acuJ1QdQ9FayosNNlJrCw"]
error: Error: Cannot add or update a child row: a foreign key constraint fails (`test`.`ordered_payable_item`, CONSTRAINT `FK_3d6e08f6651236bb558d5fc37ca` FOREIGN KEY (`orderId`) REFERENCES `order` (`id`))
query: ROLLBACK
If I remove generateId() or create parent entity (Order) everything works well, but I have to use nanoid as primary key and childentity here.