Как сохранить отношение в @ManyToMany в typeORM

Есть 2 объекта с именами Article и Classification. И их отношение @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[];
    }

Могу сохранить Article и Classification удачно. Но я не знаю, как сохранить их отношение.

Я попытался сохранить отношение с помощью кода ниже:

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;
  }

person Eve-Sama    schedule 26.02.2019    source источник


Ответы (2)


Как сохранить отношения?

Предположим, у вас есть массив статей, и вы хотите создать связь с классификационным объектом. Вы просто назначаете массив свойству 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);
}
person Kim Kern    schedule 26.02.2019
comment
Я попробовал ваш метод. И у меня это не сработало. Я обновил свой вопрос, можете ли вы помочь дальше? - person Eve-Sama; 02.03.2019
comment
Теперь это другая проблема: вы публикуете classifications с их id. id - это PrimaryGeneratedColumn объекта classification. Если вы хотите создать новый объект, вы не должны включать первичный столбец, иначе объект будет обновлен, а не создан, если первичный столбец (id) уже существует. - person Kim Kern; 02.03.2019
comment
Но я просто хочу сохранить их отношения. Не сохранять сущность Classification. Я действительно хочу создать новый объект, но не classification, просто новое отношение classification и article. И мне нужно, чтобы id из Classification, автоматически сгенерированный со значением автоинкремента, когда я вставляю новый Classification. Я не понимаю, как реализовать мою цель? - person Eve-Sama; 02.03.2019
comment
Итак, все сущности уже существуют; вы просто хотите создать связь между сущностями !? Затем просто загрузите свой классификационный объект из базы данных findOne(classificationId), назначьте статьи классификационному объекту, который вы загрузили из базы данных, а затем сохраните классификационный объект. - person Kim Kern; 02.03.2019
comment
Я сделал то, что ты сказал. Но с этим было что-то не так. Я разместил код в вопросе. - person Eve-Sama; 02.03.2019
comment
Вы создаете новую сущность const classification = new Classification(); вместо загрузки существующей из базы данных. - person Kim Kern; 02.03.2019
comment
Вы уверены, что просматриваемый код находится ниже Just look below code please? - person Eve-Sama; 02.03.2019
comment
Позвольте нам продолжить это обсуждение в чате. - person Kim Kern; 02.03.2019
comment
Спасибо, я попытался добавить ManyToMany в статью, теперь у меня есть ManyToMany в статье и классификации, но у меня все еще не работает. И я попробовал другое решение: найти все статьи, содержащиеся в классификации, например, classification{id:4,articles:[article1,article2]}, затем classification.articles.push(newArticle). Тогда это сработает. Но я знаю, что это ужасное решение. - person Eve-Sama; 03.03.2019
comment
Думаю, я разобрался. Когда я создаю объект Классификации. И установите его id. В то время статьи пусты. Итак, я вставляю в него одну статью, типорма будет думать, что у нее только одна статья, даже если у нее много статей в базе данных? Итак, предыдущее решение верно? - person Eve-Sama; 03.03.2019
comment
Боюсь, я не могу полностью понять, что вы делаете. : - / Однако вам следует либо создать новую сущность без установки id, либо загрузить существующую сущность из базы данных с ее id. - person Kim Kern; 03.03.2019
comment
эмм, извини за беспокойство, потому что мой английский не очень хорош. Как насчет общения по ссылке, которую вы разместили вчера? - person Eve-Sama; 03.03.2019

в моем случае у меня есть пользователь и роль, сначала вам нужно инициализировать свой manytomany в своих объектах:

в пользовательском объекте:

@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);
person Salah ED    schedule 10.05.2021