#javascript #postgresql #nestjs #typeorm
Вопрос:
помогите мне, пожалуйста. Я действительно не понимаю, как это работает, у меня есть сущность под названием Product, имеющая множество связей с другой сущностью под названием Car с включенным флагом true.
@Entity()
export class Product {
@PrimaryGeneratedColumn()
id: number
@ManyToMany(() => Car, { cascade: true })
@JoinTable()
cars: Car[]
}
Сущность автомобиля не содержит ссылки на сущность продукта. Это означает, как я думаю, что отношение однонаправленное.
Поэтому, когда я сохраняю продукт, я устанавливаю машины для этого продукта:
const cars = await this.carService.getByIds(createProductDto.cars)
const newProduct = this.productsRepository.create({
...createProductDto,
cars
})
await this.productsRepository.save(newProduct)
Я получаю объекты автомобилей по идентификаторам и сохраняю их в продукте. Это хорошо работает. Я не уверен, что это лучший способ, но другого я не знаю.
Проблемы возникают, когда я пытаюсь обновить какой-либо существующий продукт в базе данных. Я получаю ошибки при выпадении:
ERROR [ExceptionsHandler] duplicate key value violates unique constraint "PK_f7b49d8fd8d09ea2fc2e7542f3f"
или
Error: Cannot query across many-to-many for property cars
или что-то другое…
Помогите мне, пожалуйста. Я хочу понять, как лучше всего работать с такими отношениями. Каков наилучший способ его создания, обновления и удаления?
Спасибо
Ответ №1:
Вы утверждаете, что у вас есть М:М между автомобилями и продуктами, но это не то, что вы описываете. Вы описываете 1:M для автомобилей и продуктов. Ссылка на автомобили в таблице «Продукты» означает, что в данном автомобиле может быть много Продуктов, но данный продукт может использоваться только 1 автомобилем. Это результат ссылки на автомобили из продуктов (я бы не классифицировал их как однонаправленные, поскольку, учитывая, что я могу получить один из них, другой, это просто число, которое я могу получить, меняется). Тем не менее, я верю, что вы хотите M:M. Типичная реализация для M:M требует 3-й таблицы. При такой конфигурации ни таблица автомобилей, ни таблица продуктов не ссылаются друг на друга, вместо этого третья таблица ссылается на обе. К сожалению, я не знаю или не узнаю вашего менеджера запутывания (ORM, который вы используете). Поэтому я набросаю возможное определение ddl для таблиц.
create table cars ( car_id integer generated always as identity primary key
, vin text
, manufacturer text
-- other Car attributes
);
create table products( prod_id integer generated always as identity primary key
, manufacturer text
-- other product
);
-- create the reference/intersection table for M:M Cars:Products
create table car_products( car_id
, prod_id
-- attributes that pertain only to the combination of
-- of the other tables
, model_code text
, serial_number text
-- constraints
, constraint car_products_pk
primary key (car_id, prod_id)
, constraint car_products_2_cars_fk
foreign key (car_id)
references cars(car_id)
on delete cascade
, constatint car_products_2_products_fk
foreign key(prod_id)
references products(prod_id)
on delete cascade
);
Теперь с помощью этой настройки данный автомобиль может иметь любое количество продуктов, и данный продукт может использоваться любым количеством автомобилей. (Примечание: В этой настройке продукт отличается от детали.) Я надеюсь, что это поможет вам понять отношения 1:M против отношений M:M.
Комментарии:
1. Одна деталь может быть применена к нескольким автомобилям. Например, эта деталь представляет собой двигатель под названием LY7 (двигатель GM объемом 3,6 л). Этот двигатель может быть применен к: Cadillac CTS, Cadillac STS, Cadillac SRX, Holden Commodore, Buick Park Avenue, Buick LaCrosse, Suzuki XL7 и Pontiac G8. Я имею в виду, что мне нужно много-много отношений. Также я использую typeorm ORM, и в документации говорится, что третья таблица будет создана автоматически: typeorm.io/#/many-to-many-relations/. … И это работает, потому что в postgresql была создана таблица product_cars_car