We are launching the Spring 3.1 / Hibernate 4 / Java 7 / Tomcat 7 / MSSQL 2008 R2 web application. We must deal with obsolete data and archived data. When extracting data from the archive, we need to use the original unique identifier so that other (unarchived) records are correctly restored. These identifiers are stored in the primary key / auto increment field.
So far, when we used Spring 3.0 / Hibernate 3.5, the following code worked so that INSERT would retrieve the record back to the corresponding table (we already have session , entity and fullTableName in the scope):
session.doWork( new Work() { @Override public void execute(Connection connection) throws SQLException { PreparedStatement statement = null; try { statement = connection.prepareStatement(String.format("SET IDENTITY_INSERT %s ON", fullTableName)); statement.execute(); session.save(entity); statement = connection.prepareStatement(String.format("SET IDENTITY_INSERT %s OFF", fullTableName)); statement.execute(); } finally { } } });
As I mentioned, all this worked fine in Hibernate 3.5, but now that we have upgraded to Hibernate 4, it stops working. Is there anything with a difference between Work and IsolatedWork?
To solve the problem and avoid problems with the working interface, we tried the following:
session.createSQLQuery(String.format("SET IDENTITY_INSERT %s ON", fullTableName)).executeUpdate(); session.save(entity); session.createSQLQuery(String.format("SET IDENTITY_INSERT %s OFF", fullTableName)).executeUpdate();
However, this did not work either. In particular, the resulting exception is java.sql.SQLException: Cannot insert explicit value for identity column in table 'Employee' when IDENTITY_INSERT is set to OFF. However, it should be clear that we are trying to set it to ON.
We made a trace of the SQL Server Profiler situation and found something interesting. Something sets IMPLICIT_TRANSACTIONS ON in each of our transactions. Here are a few examples from Profiler tracing (I replaced our actual <schema> scheme and some large data bits with shorter labels):
SET IMPLICIT_TRANSACTIONS ON go declare @p1 int set @p1=55 exec sp_prepare @p1 output,N'',N'SET IDENTITY_INSERT <schema>.Employee ON',1 select @p1 go exec sp_execute 55 go declare @p1 int set @p1=56 exec sp_prepare @p1 output,N'<parameters for the INSERT>',N'insert into <schema>.Employee (<all the column names>) values ( <all the parameters> )',1 select @p1 go exec sp_execute 56,<the actual values to insert> go IF @@TRANCOUNT > 0 ROLLBACK TRAN go IF @@TRANCOUNT > 0 COMMIT TRAN SET IMPLICIT_TRANSACTIONS OFF go exec sp_execute 54,N'Error writing EMPLOYEE archive record. ',<an id>,N'1' go
Now we specifically set IMPLICIT_TRANSACTIONS to OFF, through Connection.setAutoCommit (false) in our transaction (transactions are managed through Spring @Transactional and Hibernate Transaction Manager). Obviously this does not work, but what are the alternatives besides using setAutoCommit, and why will it work in Spring3.0 / Hibernate 3.5, but not Spring 3.1 / Hibernate 4?
Thanks for any thoughts or suggestions - we are at an impasse.