Mikro-ORM still cascades while persisting even when deactivated

1.2k Views Asked by At

I must be doing something wrong with my entity relationships because whenever I try to persist a parent entity with its children, Mikro-ORM keeps trying to persist the children as well, even if cascading has been deactivated for the given properties.

I have some concerts:

import { Entity, PrimaryKey, Property, SerializedPrimaryKey, Collection, ManyToMany } from "@mikro-orm/core";
import { ObjectId } from 'mongodb';
import { Artist } from "./artist";

type Props = {
    readonly _id: ObjectId;
    readonly artists?: Collection<Artist>;
}

@Entity()
export class Concert {
    constructor(private props: Props) { Object.assign(this, props) }

    /* Private variables */
    @PrimaryKey()
    readonly _id!: ObjectId;

    @SerializedPrimaryKey()
    id!: string; // won't be saved in the database

    @ManyToMany({ entity: () => Artist, mappedBy: 'concerts', cascade: [] }) // cascading should be deactivated
    public readonly artists = new Collection<Artist>(this);
}

and some artists :

import { Entity, PrimaryKey, Property, SerializedPrimaryKey, Collection, ManyToMany, Cascade, OneToMany } from "@mikro-orm/core";
import { ObjectId } from 'mongodb';
import { Concert } from "./concert";
import { User } from "./user";

type Props = {
    readonly _id: ObjectId;
    readonly concerts?: Collection<Concert>;
    readonly name: string;
}

@Entity()
export class Artist {
    constructor(private props: Props) { Object.assign(this, props) }

    /* Private variables */
    @PrimaryKey()
    readonly _id!: ObjectId;

    @SerializedPrimaryKey()
    id!: string; // won't be saved in the database

    @ManyToMany({ entity: () => Concert, mappedBy: 'artists', cascade: [], owner: true }) // cascading should be deactivated
    public readonly concerts = new Collection<Concert>(this);

    @Property()
    public readonly name!: string;
}

I already have an artist saved in my mongodb database, under the artist collection with the example ObjectId _id : ObjectId("a").

When trying to persist like so :

const concert = new Concert({ _id: new ObjectId() });

concert.artists.add(new Artist({ "_id": new ObjectId("a"), "name": "" })) 

await concertRepository.persistAndFlush(concert)

I get the following message:

UniqueConstraintViolationException: E11000 duplicate key error collection: db.artist index: _id_ dup key: { _id: ObjectId('a') }

Does anyone know what I'm doing wrong?

2

There are 2 best solutions below

0
On BEST ANSWER

So I found where I went wrong, adding the artist like such :

concert.artists.add(new Artist({ "_id": new ObjectId("a"), "name": "" })) 

just won't cut it. In order to add an existing artist, here is how to proceed :

// Use the mikro-orm findOne method from the entity manager
const artist = await artistRepository.findOne(Artist, { _id: new ObjectId('a') })
// Add it to the collection
if (artist) concert.artists.add(artist);
// Now I can persist the concert and the artist is not duplicated
await concertRepository.persistAndFlush(concert)
1
On

If you don't want to load the artist, you can use em.getReference():

concert.artists.add(artistRepository.getReference('a'));
await concertRepository.persistAndFlush(concert);

Also note that if the concert entity here is already managed (loaded from database), you can just call em.flush(), no need to persist it again (the EM already knows about it).