2012-10-16 13 views
7

Spring 3.1/Hibernate 4/Java 7/Tomcat 7/MSSQL 2008 R2 web uygulaması çalıştırıyoruz. Eski veriler ve arşivlenmiş verilerle ilgilenmeliyiz. Bir arşivdeki verileri ayıklarken, orijinal (benzersiz) tanımlayıcıyı, diğer (arşivlenmemiş) kayıtların doğru şekilde yeniden hidratlanmasını sağlayacak şekilde kullanma ihtiyacımız vardır. Bu tanımlayıcılar birincil anahtar/otomatik artış alanında saklanır.Hibernate 3.5 vs 4 IDENTITY_INSERT sorunları

:

ilkbahar 3.0 kullanılarak zaman dilimi,/3.5 hazırda bekleme önce, aşağıdaki kod, (daha önce değişkenler session, entity ve fullTableName kapsamında olması) da uygun tabloya geri bir ekstre kaydı eklemek için çalışmıştır

Daha önce de belirttiğim gibi, tüm bunlar Hazırda Bekletme 3.5'de iyi çalıştı, ancak şimdi Hazırda Bekletme 4'e geçtiğimizde, çalışmayı durdurdu. Work ve IsolatedWork arasındaki farkla ilgili bir şey var mı?

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(); 

Ancak bu da işe yaramadı: Sorunu çözmek ve herhangi Çalışma arayüzü sorunları önlemek için bir çaba

, aşağıdaki çalıştı. Özel olarak, atılan istisna java.sql.SQLException: Cannot insert explicit value for identity column in table 'Employee' when IDENTITY_INSERT is set to OFF.'dur. Yine de, açık olması için ağrıları aştığımızın açık olması gerekir.

Durumun SQL Server Profiler izini inceledik ve ilginç bir şey bulduk. İşlem birimlerimizin her birinde bir şey IMPLICIT_TRANSACTIONS ON ayarlanıyor. Bağlantı yoluyla, KAPALI olmak Şimdi, özellikle IMPLICIT_TRANSACTIONS ayarlarken

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 

: Burada Profiler izlemesinde bazı örnek çıktı (I yerini ettik bizim <schema> ile fiili şema ve daha kısa etiketlerle bazı verilerin büyük bit) var .setAutoCommit (false) işlemimizde (işlemler Spring @ Transactional ve Hibernate Transaction Manager üzerinden yönetiliyor). Açıkçası, bu işe yaramıyor, ama setAutoCommit kullanmanın dışında alternatifler nelerdir ve neden Spring3.0/Hibernate 3.5'de çalışır, ancak Spring 3.1/Hibernate 4 değil?

Herhangi bir düşünce ya da öneriniz için teşekkür ederiz - biz güldük.

cevap

2

Eh,

Çalışmalarımız çağrı dahili olarak bir java.sql.PreparedStatement kullanılan ... ince bir çözüm oldu ve o zaman execute() yöntemi denir. Görünüşe göre, bu kod örneklerinin bazıları gösterdiği gibi, SQL Server'a kendi saklı yordamında komutu kaydırmasını söyler.

Biz onun execute() yöntemi bir PreparedStatement basitçe bir java.sql.Statement kullanarak ve arama değiştirildi:

session.doWork(new Work() 
{ 
    @Override 
    public void execute(Connection connection) throws SQLException 
    { 
     Statement statement = null; 
     try 
     { 
      statement = connection.createStatement(); 
      statement.execute(String.format("SET IDENTITY_INSERT %s ON", fullTableName)); 

      session.save(entity); 

      statement = connection.createStatement(); 
      statement.execute(String.format("SET IDENTITY_INSERT %s OFF", fullTableName)); 
     } 
     finally 
     { /* close the statement */ } 
    } 
}); 

Yani, ne fark eder? Anlayabildiğimiz kadarıyla, PreparedStatement, önceden derlenmiş SQL üretir, oysa Statement, statik SQL üretir ... IDENTITY_INSERT için tam olarak aradığımız şey!

Ders: Birçok pislik ve kötülük kurbanları var ... dikkatli olmalıyız!

+0

Çok teşekkür ederim, bu bana çok zaman kazandırdı. –