How to save relation in @ManyToMany in typeORM

30,268

Solution 1

How to save relations?

Let's assume you have an array of articles and you want to create a relation to a classification entity. You just assign the array to the property articles and save the entity; typeorm will automatically create the relation.

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

For this to work, the article entities have to be saved already. If you want typeorm to automatically save the article entities, you can set cascade to true.

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

Your example

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

Solution 2

in my case i have user and role, 1st you have to initialize your manytomany in your entities :

in user entity :

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

in role entity :

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

in my service i create a new entity from my data then i added role data to my new entity object :

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

this is the exemple in typeorm website :

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);
Share:
30,268
Eve-Sama
Author by

Eve-Sama

I'm really willing to help everyone who's in trouble about development within my ability.I hope this community will be more fantastic and perfect becase of my join!

Updated on May 10, 2021

Comments

  • Eve-Sama
    Eve-Sama about 3 years

    There are 2 entities named Article and Classification. And the relation of them is @ManyToMany.

    Here's my question: How to save the relation?

    My code as below:

      @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[];
        }
    

    I can save the Article and Classification successful. But I'm not sure how to save the relation of them.

    I have tried to save the relation via below code:

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

    And the post data strcture like that

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

    At the beginning, it works.

    enter image description here

    But when I post the data again, the old record was replaced rather create another record.

    enter image description here

    What should I do next?

    Just look below code please.

    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;
      }
    
  • Eve-Sama
    Eve-Sama about 5 years
    I have tried your method. And it didn't work for me. I have updated my question, can u help next?
  • Kim Kern
    Kim Kern about 5 years
    This is a different problem now: You are posting the classifications with their id's. id is the PrimaryGeneratedColumn of the classification entity. If you want to create a new object, you must not include the primary column, otherwise the entity will be updated instead of created if the primary column (id) already exists.
  • Eve-Sama
    Eve-Sama about 5 years
    But I just wanna save the relation of them. Not save the entity Classification.I do wanna create a new object, but not classification, just new relation of classification and article.And I need the id of Classification automatically generated with an auto-increment value when I insert a new Classification. I'm not clear how to realize my target?
  • Kim Kern
    Kim Kern about 5 years
    Ok, so all entities already exist; you just want to create the relation between the entities!? Then just load your classification entity from the database findOne(classificationId), assign the articles to the classification entity you loaded from the database and then save the classification entity.
  • Eve-Sama
    Eve-Sama about 5 years
    I have done as what u said. But there was something wrong with it. I have posted the code in the question.
  • Kim Kern
    Kim Kern about 5 years
    You are creating a new entity const classification = new Classification(); instead of loading the existing one from the database.
  • Eve-Sama
    Eve-Sama about 5 years
    Are you sure the code you watched is below Just look below code please?
  • Kim Kern
    Kim Kern about 5 years
  • Eve-Sama
    Eve-Sama about 5 years
    thx, I have tried to add ManyToMany in Article,Now I have ManyToMany in Article and Classification,but still not work for me. And I tried another solution: find all articles that classification contains, just like classification{id:4,articles:[article1,article2]},then classification.articles.push(newArticle).Then it works. But I know this is a terrible solution.
  • Eve-Sama
    Eve-Sama about 5 years
    I guess I figure it out. When I create a object of Classification. And set its id. In that time, the articles is empty. So I push one article in it, the typeorm will think it has only one article even if it has a lot of articles in database? So the previous solution is right?
  • Kim Kern
    Kim Kern about 5 years
    Mh, I'm afraid I can't completely follow what you're doing. :-/ However, you should either create a new entity without setting an id or load an existing entity from the database with its id.
  • Eve-Sama
    Eve-Sama about 5 years
    emm,sorry to bother u, cause my english is not good. How about chatting in the linking now you posted yesterday?