Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I insert an object graph by using MikroORM?

I'm trying to create and update multiple entities (models) at once. I did this in objection ORM by using insertGraph API which actually inserts entity if it has no id and updates if it has id.

Is there a similar API in MikroORM?

Currently I'm doing this:

app.put('/articles', async (req, res) => {
  const save = req.body.articles.map(async (dto) => {
    const article = Object.assign(new Article(), dto)
    await req.em.persistAndFlush(article)
  })


  await Promise.all(save)
  res.send({ ok: true })
})

but it generates multiple transactions and I want to everything in single transaction.

like image 632
Sergii Stotskyi Avatar asked Mar 05 '23 07:03

Sergii Stotskyi


1 Answers

The problem here is that when using persistAndFlush method, you immediately persist the entity to database by awaiting the promise. Instead you can call em.persistLater(article) to mark it for persisting. Then call em.flush() afterwards, which will commit all changes to database inside single transaction.

app.put('/articles', async (req, res) => {
  req.body.articles.forEach(dto => {
    const article = Object.assign(new Article(), dto)
    req.em.persistLater(article)
  })

  await req.em.flush() // save everything to database inside single transaction
  res.send({ ok: true })
})

You can make it even simpler by preparing all entities into one array, and persistAndFlush that instead:

app.put('/articles', async (req, res) => {
  const articles = req.body.articles.map(dto => Object.assign(new Article(), dto))
  await req.em.persistAndFlush(articles) // save everything to database inside single transaction
  res.send({ ok: true })
})

Also, instead of using Object.assign(), you can use IEntity.assign() method on the entity, which will also take care of creating references from plain identifiers:

const article = new Article().assign(dto)

More about IEntity.assign() can be found in the docs:

https://b4nan.github.io/mikro-orm/entity-helper/

You could also use EntityManager.create() helper, which will construct the entity for you - the benefit of this is that it will automatically handle constructor parameters, passing them to constructor instead of assigning them directly.

const article = req.em.create(Article, dto)
like image 93
Martin Adámek Avatar answered Mar 15 '23 14:03

Martin Adámek