typeorm: EventSubscriber not getting updated values for update using queryBuilder and manager.update methods.

Issue type:

[x] question [ ] bug report [ ] feature request [ ] documentation issue

Database system/driver:

[ ] cordova [ ] mongodb [ ] mssql [ ] mysql / mariadb [ ] oracle [x] postgres [ ] sqlite [ ] sqljs [ ] react-native

TypeORM version:

[ ] latest [ ] @next [ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem: Whenever entity is update using queryBuilder update method or entity update method, the EventSubscriber’s afterUpdate method gets triggered, but the UpdateEvents entity, databaseEntity, updatedColumns, updateRelations are always empty. These fields are populated only when the updates are done using save methods. Is this intended behaviour.

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Reactions: 8
  • Comments: 22 (5 by maintainers)

Commits related to this issue

Most upvoted comments

TypeORM is huge and has lot of small functionality and lot of quirks. There are hundred such small details all of them simply can’t be documented not only because its impossible to keep in mind all small facts like this, but also because it will complicate documentation. Maybe I’ll add this to documentation in the future.

wow, wow so many dislikes on my above post ^ Okay, okay, now I definitely know we need to add this to the docs.

maybe the listenerMethod should just be renamed (+ aliased for backwards compatibility) to afterSaveto avoid this confusion.

But then, what’s the preferred approach to reliably act upon update of an entity, with data about the entity itself available? By reliably, I mean no matter of the way the data is updated, whether is .save() or .update(), or query builder or whatever.

I don’t want to be forced to remember to use certain way of updating just because somewhere on the other end of the repository there’s a subscriber that reacts differently to different methods.

TypeORM gives you lots of control over your database interactions. You can use high-level, fully-featured but less efficient operations, or low-level and fast operations.

  • When executing high-level operations (EntityManager.save), TypeORM has full access to the entity and can do additional queries to determine whether inserting or updating. Therefore TypeORM can call subscribers with entities.
  • When executing primitive operations ( EntityManager.insert, EntityManager.update, EntityManager.delete), TypeORM does not always have access to entities, but does know the operation. Therefore TypeORM can call subscribers, but cannot always provide the entities.
  • When executing raw SQL queries (QueryRunner.query), TypeORM does not know what you’re doing and doesn’t have access to entities or subscribers.

Each method has tradeoffs. You have to decide the best fit for your use case.

If you want to see exactly what the orm is doing, turn on logging and check out the SQL being executed for your operations

@NickKelly1 you can call the save method instead of the update method carbon (1)

Thanks for your patience, I get it now.

Since this is not quite obvious, should it be mentioned in the docs?

https://github.com/typeorm/typeorm/blob/master/docs/listeners-and-subscribers.md#beforeupdate

@pleerock then it works - is this the desired behavior? Because this feels confusing.

Listeners are confusing but because of flexibility and functionality orm provides. With save you can always have an entity or partial entity which you insert/update. With update and update query builder you have more like a set of values to be used in UPDATE query. For example:

update({
     id: 1,
     counter: () => "counter + 1"
});

counter in entity is actually a number, but this is a valid syntax for update, and if we pass this update set to listener we can’t call it entity anymore.