如何在typeORM中保存@ManyToMany中的关系

Posted

技术标签:

【中文标题】如何在typeORM中保存@ManyToMany中的关系【英文标题】:How to save relation in @ManyToMany in typeORM 【发布时间】:2019-07-20 00:31:16 【问题描述】:

有 2 个实体名为 ArticleClassification。他们的关系是@ManyToMany

这是我的问题:如何保存关系?

我的代码如下:

  @Entity()
    export class Article 
        @PrimaryGeneratedColumn()
        id: number;

        @Column()
        name: string;

        @CreateDateColumn()
        createTime: Date;

        @UpdateDateColumn()
        updateTime: Date;

        @Column(
            type: 'text',
        )
        content: string;

        @Column(
            default: 0,
        )
        likeAmount: number;

        @Column(
            default: 0,
        )
        commentAmount: number;
    

    @Entity()
    export class Classification 
        @PrimaryGeneratedColumn()
        id: number;

        @CreateDateColumn()
        createTime: Date;

        @UpdateDateColumn()
        updateTime: Date;

        @Column()
        name: string;

        @ManyToMany(type => Article)
        @JoinTable()
        articles: Article[];
    

我可以成功保存ArticleClassification。但我不确定如何保存它们的关系。

我已尝试通过以下代码保存关系:

async create(dto: ArticleClassificationDto): Promise<any> 
    const article = this.repository.save(dto);
    article.then(value => 
      console.log(value);//console the object article
      value.classification.forEach(item => 
        const classification = new Classification();
        classification.id = item.id;
        classification.articles = [];
        classification.articles.push(value);
        this.classificationService.save(classification);
      )
    );
    console.log(article);
    return null;
  

还有这样的帖子数据结构

    
        "name":"artile name",
        "content":"article content",
        "classification":[
            "id":4
        ,
            "id":3
        ]
    

一开始,它有效。

但是当我再次发布数据时,旧记录被替换而不是创建另一个记录。

接下来我该怎么做?

请看下面的代码。

async create(dto: ArticleClassificationDto): Promise<any> 
    this.repository.save(dto).then(article => 
      article.classification.forEach(item => 
        this.ClassificationRepository.findOne(
          
            // the privous method is get all the articles from databse and push into this array
            // relations: ['articles'],
            where:  id: item // now I change the data strcture, just contains id instead of id
          
        ).then(classification => 
          // console.log(article);
          console.log(classification);
          // cmd will show ' UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'push' of undefined' withous below line code. But if I init the array manually,the old record will be replaced again.
          // classification.articles = [];
          classification.articles.push(article);
          this.ClassificationRepository.save(classification);
        );
      )
    )
    return null;
  

【问题讨论】:

【参考方案1】:

如何保存关系?

假设您有一个文章数组,并且您想要创建与分类实体的关系。您只需将数组分配给属性articles 并保存实体; typeorm 会自动创建关系。

classification.articles = [article1, article2];
await this.classificationRepository.save(classification);

为此,必须已保存文章实体。如果想让typeorm自动保存文章实体,可以将cascade设置为true

@ManyToMany(type => Article, article => article.classifications,  cascade: true )

你的例子

async create(dto: ArticleClassificationDto): Promise<any> 
  let article = await this.repository.create(dto);
  article = await this.repository.save(article);
  const classifications = await this.classificationRepository.findByIds(article.classification, relations: ['articles']);
  for (const classification of classifications) 
    classification.articles.push(article);
  
  return this.classificationRepository.save(classifications);

【讨论】:

我试过你的方法。它对我不起作用。我已经更新了我的问题,接下来你能帮忙吗? 现在这是一个不同的问题:您将classifications 与他们的id 一起发布。 idclassification 实体的 PrimaryGeneratedColumn。如果要创建新对象,则不能包含主列,否则如果主列 (id) 已存在,实体将被更新而不是创建。 但我只想保存他们的关系。不保存实体Classification。我确实想创建一个新对象,但不是classification,只是classification article的新关系。我需要Classificationid自动生成自动- 当我插入一个新的Classification 时增加值。我不清楚如何实现我的目标? 好的,所以所有实体都已经存在;您只想创建实体之间的关系!?然后只需从数据库findOne(classificationId)加载您的分类实体,将文章分配给您从数据库加载的分类实体,然后保存分类实体。 我已经按照你说的做了。但它有问题。我已经在问题中发布了代码。【参考方案2】:

在我的情况下,我有用户和角色,首先你必须在你的实体中初始化你的多线程:

在用户实体中:

@ManyToMany((type) => Role, 
    cascade: true,
  )
  @JoinTable(
    name: "users_roles",
    joinColumn:  name: "userId", referencedColumnName: "id" ,
    inverseJoinColumn:  name: "roleId" 
  )
  roles: Role[];

在角色实体中:

  //Many-to-many relation with user
  @ManyToMany((type) => User, (user) => user.roles)
  users: User[];

在我的服务中,我从我的数据创建一个新实体,然后我将角色数据添加到我的新实体对象:

let entity = await this.userRepository.create(data);
let entity2 = 
        ...entity,
        roles: data.selectedRoles,
      ;
const user = await this.userRepository.save(entity2);

这是typeorm网站中的例子:

const category1 = new Category();
category1.name = "animals";
await connection.manager.save(category1);

const category2 = new Category();
category2.name = "zoo";
await connection.manager.save(category2);

const question = new Question();
question.title = "dogs";
question.text = "who let the dogs out?";
question.categories = [category1, category2];
await connection.manager.save(question);

【讨论】:

以上是关于如何在typeORM中保存@ManyToMany中的关系的主要内容,如果未能解决你的问题,请参考以下文章

NestJS + TypeORM 中的 JoinTable 问题

保存方法manytomany

Typeorm 插入数据,即使它存在

使用 TypeORM 在 Postgres bytea 上保存缓冲区仅存储 10 个字节

使用 Django admin 时未保存 ManyToMany 字段

Typescript TypeORM 创建和保存数据的最佳方式