Eseguiamo un'applicazione Web Spring 3.1/Hibernate 4/Java 7/Tomcat 7/MSSQL 2008 R2. Dobbiamo occuparci di dati legacy e dati archiviati. Quando estraiamo i dati da un archivio, abbiamo bisogno di utilizzare l'identificatore univoco originale in modo che altri record (non archiviati) si reidratino correttamente. Questi identificativi sono memorizzati nel campo chiave primaria/incremento automatico.Hibernate 3.5 vs 4 problemi IDENTITY_INSERT
Prima di ora, quando usavamo Primavera 3.0/Hibernate 3.5, il seguente codice lavorato per inserire un record di estratto di nuovo nella sua tabella appropriata (abbiamo già le variabili session
, entity
, e fullTableName
a portata):
Come ho già detto, tutto ha funzionato bene in Hibernate 3.5, ma ora che abbiamo aggiornato a Hibernate 4, ha smesso di funzionare. C'è qualcosa con la differenza tra Work e IsolatedWork?
Nel tentativo di risolvere il problema, e di evitare eventuali problemi di interfaccia lavoro, abbiamo provato il seguente:
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();
Tuttavia, questo non ha funzionato neanche. Nello specifico, l'eccezione che viene generata è java.sql.SQLException: Cannot insert explicit value for identity column in table 'Employee' when IDENTITY_INSERT is set to OFF.
Tuttavia, dovrebbe essere chiaro che stiamo attraversando dei problemi per impostarlo.
Abbiamo tracciato una traccia della situazione di SQL Server Profiler e trovato qualcosa di interessante. Qualcosa sta impostando IMPLICIT_TRANSACTIONS su ciascuno dei nostri corpi delle transazioni. Ecco qualche esempio di output dalla traccia di Profiler (ho sostituito il nostro schema vero e proprio con <schema>
, e alcuni grandi bit di dati con etichette più brevi):
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
Ora, stiamo specificamente allestendo IMPLICIT_TRANSACTIONS di essere fuori, mediante la connessione .setAutoCommit (false) nella nostra transazione (le transazioni vengono gestite tramite Spring @Transactional e Hibernate Transaction Manager). Ovviamente, questo non funziona, ma quali sono le alternative oltre all'uso di setAutoCommit e perché dovrebbe funzionare in Spring3.0/Hibernate 3.5 ma non Spring 3.1/Hibernate 4?
Grazie per qualsiasi pensiero o suggerimento - siamo perplessi.
Grazie mille, questo mi ha fatto risparmiare un sacco di tempo. –