I'm trying to create many related entities in a transaction. There are recursive relations between these e.g.:
@Entity()
class A {
@OneToMany(() => B, b => b.A)
bs = new Collection<B>(this);
@ManyToOne(() => C)
c!: C;
}
@Entity()
class B {
@ManyToOne(() => A)
a!: A;
}
@Entity()
class C {
}
To keep things simple, I'll only use 3 entities, but in my case, the problem is on a bigger scale (20+ entities). I first create entity A where C is a required field. Then I create a bunch of Bs and assign them to A. At this point, all Bs have a fully populated A with all the C's and all the B's created so far. It seems that since A is already loaded in the context, it automatically attaches the same object to B, but I want it to be passed as a reference only. This makes my final A object explode with recursive, unnecessary relations.
Is the only option to define B.a as a Reference to A?
The entity graph is always consistent, you can't have the same entity loaded at one place and not loaded in another. What you can do is controlling how the entities are serialized.
One way is using explicit serialization, so the serialize()
helper which you pass the populate hint.
console.log(serialize(entities, { populate: ['a.b'] }));
https://mikro-orm.io/docs/serializing#explicit-serialization
An alternative would be a recently added setSerializationContext
method on the entity wrapper, which you can use to explicitly do what the ORM does when loading entities. This part is currently not documented, but it's pretty much the same, just for the implicit serialization (e.g. when you call JSON.stringify
on the entity, or explicitly via wrap(entity).toObject()
).
for (const entity of entities) {
wrap(entity, true).setSerializationContext({ populate: ['a.b'] });
}
console.log(JSON.stringify(entities, null, 2));
You can also use partial loading this way with the fields
or exclude
parameters.