New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question: persist nested entities #678
Comments
Nope, it should not be an array, collections are represented via
Your problem is probably in the constructor, you cannot replace the collection instance (which this code does).
You can use Anyway, first enable debug mode and add a |
I see. I tried to change it to
and got this error:
I've turned on debug mode and no sql has been executed yet after the change above. |
And what is in the data? |
Also, after re-reading some pages, all the examples have the objects initialized manually, as in this page: https://mikro-orm.io/docs/entity-manager#persisting-and-cascading
Is it needed that all the relations are initialized beforehand (via constructors, or
since that's what I'm aiming to do with my code at the OP. Sorry if this kind of derails the issue, but I think its similar. |
Maybe create a reproduction. It should work with the assign method as well as with em.create(). PK will be considered as existing entity, and an object as new one. |
Okay, I'll try to setup a reproduction repo |
Okay, I made a repository here: https://github.com/davenathanael/mikro-orm-678 While I made it, I fixed the Regarding to the Collection being printed as an object, I tried the repo without using The nested entity is not being persisted on DB is explained on the repository readme. Thanks! :) |
There is no need to use class-transformer here, MikroORM handles the serialization internally (each entity has toJSON() method, you can also override it to customize the bahaviour). Cant help with that, never used it myself (never even needed it). |
Ah I see. I'm using |
You are passing Also having those object ctor params, ORM will never pass them to your constructor - it works only when you have one param per property (and the names must match, e.g. Unfortunately -const recipe = em.create(Recipe, data);
+data.ingredients = (data as any).ingredient_usage;
+const recipe = wrap(new Recipe()).assign(data, { em: this.em }); Then it will properly construct the entity and assign the collection items, firing 2 queries in a transaction: [query] begin
[query] insert into `recipe` (`name`) values ('Recipe 1') [took 1 ms]
[query] insert into `ingredient_recipe_usage` (`amount`, `ingredient_id`) values (1, 1) [took 1 ms]
[query] commit Will need to verify if this still happens in v4, as it should work with the em.create() too. |
My bad, sorry. It is a bad example because my use case is to have the request payload the same as how it is stored at DB following the ORM's naming strategy (Underscore), I didn't think of that when I made that example. Now it is sorted out because I use Okay, currently I'm able to follow along and produce the same result as yours there, with |
Mmmm I see, yes that is supported, the problem is how the const recipe = new Recipe();
recipe.ingredients.add(...); // this way it would be propagated to the owning side Will try to do something about this in v4, its really confusing, and as I said, the way with |
Ah I see, thanks for explaining :), its ok I can do manually for now. Tried to do it and decided to use a DTO for the controller, and changed the service method like so: async createOne(dto: CreateRecipeDto): Promise<Recipe> {
const recipe = new Recipe();
recipe.name = dto.name;
recipe.sellingPrice = dto.sellingPrice;
const ingredients = await Promise.all(dto.ingredients.map(async (u) => {
const usage = new IngredientRecipeUsage();
usage.amount = u.amount;
usage.ingredient = await this.ingredientRepo.findOneOrFail({ id: u.ingredient });
return usage;
}));
console.log(ingredients);
recipe.ingredients.add(...ingredients);
console.log('created recipe:');
console.log(recipe);
await this.repo.persistAndFlush(recipe);
return recipe;
} and this is the log I printed, with the
I'm still getting no |
Can you upgrade your repository? For me it does work: [query] begin
[query] insert into `recipe` (`name`) values ('Recipe 1') [took 3 ms]
[query] insert into `ingredient_recipe_usage` (`amount`, `ingredient_id`, `recipe_id`) values (1, 1, 6) [took 1 ms]
[query] commit Btw if you do not want to load the (I am also getting some class-transformer recursion error, but that is outside of the scope of what I can help with - in general you should serialize the entity via |
Ah, that's new to me. It'll be cleaner since I do not want to actually load the entity and having the repository there. Thanks!
Yeah sorry didn't mention that on my last message, I do comment out the
Anyway, I've update the issue repository https://github.com/davenathanael/mikro-orm-678, when you have the time please kindly check it :) Thank you so much in advance:) |
Previously `em.create()` did not handle collection updates correctly, basically ignoring all the values if the property was not M:N owning side. With this fix, both `em.create()` and `wrap(e).assign()` properly handled collection updates, including propagation to the owning sides. Closes #678
Previously `em.create()` did not handle collection updates correctly, basically ignoring all the values if the property was not M:N owning side. With this fix, both `em.create()` and `wrap(e).assign()` properly handled collection updates, including propagation to the owning sides. Closes #678
Both The problem with your example repository is that you do not define the 1:m correctly - you are missing @OneToMany({
entity: () => IngredientRecipeUsage,
orphanRemoval: true,
eager: true,
mappedBy: usage => usage.recipe,
})
ingredients = new Collection<IngredientRecipeUsage>(this); I also made the |
My bad! Sorry didn't realised I missed the Whoa that's great, I'm looking forward to v4! Cheers :D |
Well not really your bad, there should have been some validation, pretty much all the other entity definition mistakes are validated, its weird that I forgot to validate this one :] |
Previously `em.create()` did not handle collection updates correctly, basically ignoring all the values if the property was not M:N owning side. With this fix, both `em.create()` and `wrap(e).assign()` properly handled collection updates, including propagation to the owning sides. Closes #678
Previously `em.create()` did not handle collection updates correctly, basically ignoring all the values if the property was not M:N owning side. With this fix, both `em.create()` and `wrap(e).assign()` properly handled collection updates, including propagation to the owning sides. Closes #678
Hello, I'm trying to persist an entity with a nested entity inside it, but the nested one does not persisted on DB and the return value of the OneToMany is not an array either (when logged to console or returned as JSON). Here's the structure:
MikroORM is in use together with NestJS, here's a snippet of the controller and service:
Given the request payload and its response:
I'm wondering what did I do wrong and how to resolve:
ingredients
JSON returned an object while I wanted an array (since its aOneToMany
, should beIngredientRecipeUsage[]
, seems it's theCollection<IngredientRecipeUsage>
instead?ingredients
field, while provided on the request body, does not persisted on the DB.What I have read is that entities are by default cascading when persisted, eventhough I added the
Cascade.ALL
just to make sure. What did I miss/do wrong?The text was updated successfully, but these errors were encountered: