如何在 TypeOrm 中保存多对多关系

时间:2021-04-07 10:42:58

标签: javascript typescript typeorm

我有一个产品实体,它看起来像:

@Entity('products')
export class productsEntity extends BaseEntity{
    @PrimaryGeneratedColumn()
    id: number;
    //...Unrealted Columns
    @Column({nullable: false, unique: true})
    title: string;

    @ManyToMany( type => categoryEntity, category => category.products, {cascade: true, eager: true})
    @JoinTable({name:"products_categories",
                joinColumn: {name: 'productName', referencedColumnName: 'title'},
                inverseJoinColumn: {name: 'categoryName', referencedColumnName:'title'}
              })
    categories: categoryEntity[];

    @Column({type:"text", nullable: false})
    soldBy: userEntity;
}

然后我还有一个类别实体:

@Entity('categories')
export class categoryEntity extends BaseEntity{
    @PrimaryGeneratedColumn()
    id: number;

    @Column({nullable: false, default: 'all', unique: true})
    title: string;
    

    @ManyToMany(()=> productsEntity, product => product.categories)
    products: productsEntity[];
}

由于它们之间存在多对多关系,因此我无法将任何内容保存到连接表中。此外,类别是预定义的,如果存在,则会在服务中进行检查。 我正在尝试这个存储库方法:

  async addProduct(productDetails, username, catTitle){
        const {title, description, belongsTo, price, units}  = productDetails;
        try{ 
            let newProduct = new productsEntity();
            newProduct.title = title;
            newProduct.description = description;
            newProduct.price = price;
            newProduct.units = units;
            newProduct.categories.push(catTitle);
            newProduct.soldBy = username;
            await this.manager.save(newProduct);
        }
        catch(err){
            this.logger.error(err.message);
            throw new HttpException('Failed adding Product.', HttpStatus.INTERNAL_SERVER_ERROR)
        }
    }
}

1 个答案:

答案 0 :(得分:0)

假设您将 catTitle 中的 newProduct.categories 作为标题基础与产品名称之间的关系,
这就是您使用的数据库引擎(MySQL、Postgres...) 操作和处理的内容,但在 TypeOrm 中,我们使用对象,
如果你在关系中看到:

     @ManyToMany( type => categoryEntity, category => category.products, {cascade: true, eager: true})
    @JoinTable({name:"products_categories",
                joinColumn: {name: 'productName', referencedColumnName: 'title'},
                inverseJoinColumn: {name: 'categoryName', referencedColumnName:'title'}
              })
    categories: categoryEntity[]; // you have a list of categories not a title 

**So the solution is** to pass a category object, not just the title, to do that:

      async addProduct(productDetails, username, catTitle){
            const {title, description, belongsTo, price, units}  = productDetails;
            try{ 
        
                let newProduct = new productsEntity();
                newProduct.title = title;
                newProduct.description = description;
                newProduct.price = price;
                newProduct.units = units;
                const category= await this.CategoryRepository.findOne( { where: { title: catTitle } }); // get the category 
                  //try this approach 
  newProduct.categories = newProduct?.categories ?? []; 
  newProduct.categories.push(category);
                 // or add them from category 
    category.products= category?.products?? []; 
  category.products.push(products);
await  category.save();
                newProduct.soldBy = username;
                await this.manager.save(newProduct);
            }
            catch(err){
                this.logger.error(err.message);
                throw new HttpException('Failed adding Product.', HttpStatus.INTERNAL_SERVER_ERROR)
            }
        }
    } 
相关问题