8

Why does hibernate do a select before saving an object?

I can't find useful information on internet. Is this normal behavior before every save? I found this topic, select Query Run for hibernateTemplate.save() - save, but I do not find this answer "definitive". I mean, do we have to use versioning if i want to avoid this select before saving each object?

I would appreciate all the explanations or links.

Community
  • 1
  • 1
Julia
  • 1,217
  • 8
  • 23
  • 46
  • How did you add the version column in the mapping? Please provide source. – cherouvim Apr 08 '11 at 06:33
  • @cherouvim: i have added the column in order to prevent this select. And this is how: – Julia Apr 08 '11 at 06:47
  • Could you show part of the select statement? – cherouvim Apr 08 '11 at 07:21
  • Which version of Hibernate do you use? Are you sure you call `save()`, not `saveOrUpdate()`? Also, did `select` disappear after adding versioning? – axtavt Apr 08 '11 at 08:30
  • 1
    @cherouvim @axtavt thank you for replies! my bad my bad, i was having a child objects which had the assigned IDS, and i was adding them to parent and then saving parent, so before saving, hibernate had to do selects cuz of this children, since it doesnt know if they are in database or not, cuz of their IDs :/ Thank you for help. (how do I answer this question now? :)) – Julia Apr 12 '11 at 14:07

3 Answers3

4

So Julia is right, calling Session.save() with an entity that has its IDs assigned results in hibernate doing a SELECT and then an INSERT. Fortunately there are two workarounds:

  • Don't assign your IDs up front (wasn't an option for me)
  • Call Session.persist() rather than Session.save()

The second option also works seamlessly with Envers.

Hope this saves someone else hours of hunting.

ifx
  • 561
  • 2
  • 13
  • yes, with assigned IDS select happens for sure (and there it does make sense) , however my ids were autogenerated...anyway, issue is resolved. but I will google now what does session.persist() do, for ive never used it. thanx – Julia May 08 '12 at 13:06
  • 1
    Thanks you so much! Saved me hours of hunting to optimize batch saving. – Torsten Ojaperv Jul 08 '16 at 07:47
2

I know you have answered your own question in the question's comment, but just to summarise this here are some general points.

Just to clarify, NHibernate uses 'save' as in 'SQL INSERT' and 'update' as in 'SQL UPDATE'.

I know of these common scenarios when NHibernate will fetch an object implicitly (no explicit use of s.Update) from the db before persisting it:

  1. On session_flush/transaction_commit (depending on settings) when in the mapping select-before-update is set to "true";
  2. When SaveOrUpdate is used and the identifier of the instance has a value which suggests it exists in the db;
  3. Before s.Delete.

As with your example, this may not be obvious when parent-child objects are used (but simple rules stay the same) as it may not be obvious from the code that children will be fetched.

tymtam
  • 31,798
  • 8
  • 86
  • 126
1

No, it doesn't do a select before a save. Are you sure your edit-save usecase is right? A common flow for webapps is:

  • user clicks (GET) on /products/5/edit
  • server fetches Product#5 into the http session
  • server returns the html form for editing Product#5
  • user submits (POST) form
  • server grabs Product#5 from http session
  • server populates it from request
  • server merges populated Product#5 back to the hibernate

A single sql update will be executed which also handles versioning. If the version number is out of sync, a StaleObjectStateException will be thrown.

cherouvim
  • 31,725
  • 15
  • 104
  • 153
  • hi, thanx for the answer. I clearly see that it happens before save. So, i just create new object, and then in dao i do getHibernateTemplate.save(object). He does select before, i see in the logs. I dont see reason for confusion with update :/ – Julia Apr 08 '11 at 06:15
  • OK I was confused because you mentioned about versioning. – cherouvim Apr 08 '11 at 06:17
  • well I have added a version column because i have read on hibernate forum that they say that in order to avoid this select before save, the version column should be added so that hibernate knows if object is transient or not and then he does not do a select. But i can not grasp still why he must do that if i am calling SAVE. – Julia Apr 08 '11 at 06:23