I recently moved an application from MS-SQL 2000 JDBC driver to 2005. We were using selectmethod = cursor before, but as per the FAQ, removed this after the driver upgrade.
After making the necessary configuration changes, I noticed that all inserts in the application were failing. I put Hibernate in debug logging mode and examined the raw SQL statements. I noticed that anywhere an object seemed to be joined to another object via foreign key, that foreign key would be unpopulated; even if it was a static look up table.
For instance, we have a Contract object. That contract object has a Status object. The status table is static and set to mutable=false. The contract table has a column status_id that maps to status_id in the status table. This is the beauty of hibernate such that I can call contract.setStatus(somestatus) and it will fill in the id.
However, after upgrading the SQL JAR, this just wasn't working. Every insert was getting the following Exception:
"The statement must be run before the generated keys are available"
I knew this was not a cascade issue as the status table is static.
After investigating the stacktrace, I tracked it down to insert in AbstractEntityPersister. Long story short, Hibernate was trying to use getGeneratedKeys(). After adding
<property name="hibernate.jdbc.use_get_generated_keys">false</property>
to my factory configuration, everything went back to working smoothly.
I'm posting for two reasons:
#1 So that if anyone runs into this same problem, hopefully they will find this fix,
#2 To propose, where does the bug lie? Is Hibernate incorrectly detecting that it can use generated keys (the docs say it attempts to auto detect), or is this a matter of Microsoft having an imperfect implementation in their JDBC driver? According to what sources I could find, the 2000 driver is a JDBC2 driver and 2005 is JDBC3, which is why Hibernate never tried getgeneratedkeys before; because it's a JDBC3 thing. My suspicion is that it's a Hibernate bug as in this case there was no generated key at all; the key was already there. My guess is that somehow in the process Hibernate is incorrectly guessing that these are generated columns. However, I would have to defer to someone more familiar with how Hibernate makes that determination.
|