Chúng tôi chạy ứng dụng web Spring 3.1/Hibernate 4/Java 7/Tomcat 7/MSSQL 2008 R2. Chúng ta phải xử lý dữ liệu cũ và dữ liệu đã lưu trữ. Khi trích xuất dữ liệu từ một kho lưu trữ, chúng tôi có nhu cầu sử dụng số nhận dạng duy nhất ban đầu để các bản ghi khác (không được lưu trữ) sẽ tái hydrate một cách chính xác. Các số nhận dạng này được lưu trữ trong trường khóa chính/tăng tự động.Hibernate 3.5 so với 4 sự cố IDENTITY_INSERT
Trước đến nay, khi chúng tôi đang sử dụng Spring 3,0/Hibernate 3.5, các mã sau đây làm việc để chèn một kỷ lục chiết xuất trở lại vào bảng thích hợp của nó (chúng tôi đã có các biến session
, entity
, và fullTableName
trong phạm vi):
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
{ /* close the statement */ }
}
});
Như tôi đã đề cập, tất cả đều hoạt động tốt trong Hibernate 3.5, nhưng bây giờ chúng tôi đã nâng cấp lên Hibernate 4, nó đã ngừng hoạt động. Có điều gì đó với sự khác biệt giữa Công việc và IsolatedWork không?
Trong một nỗ lực để giải quyết vấn đề, và tránh bất kỳ vấn đề giao diện làm việc, chúng tôi thử như sau:
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();
Tuy nhiên, điều này đã không làm việc một trong hai. Cụ thể, ngoại lệ được ném là java.sql.SQLException: Cannot insert explicit value for identity column in table 'Employee' when IDENTITY_INSERT is set to OFF.
Tuy nhiên, cần phải rõ ràng rằng chúng ta đang phải trải qua những cơn đau để thiết lập BẬT.
Chúng tôi đã thực hiện theo dõi SQL Server Profiler của tình huống và tìm thấy điều gì đó thú vị. Một cái gì đó đang đặt IMPLICIT_TRANSACTIONS ON trong mỗi cơ quan giao dịch của chúng tôi. Dưới đây là một số lượng mẫu từ các dấu vết Profiler (Tôi đã thay thế sơ đồ của chúng tôi thực tế với <schema>
, và một số bit dữ liệu lớn với nhãn ngắn hơn):
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
Bây giờ, chúng tôi đang thiết lập đặc biệt IMPLICIT_TRANSACTIONS là OFF, thông qua kết nối .setAutoCommit (false) trong giao dịch của chúng tôi (các giao dịch đang được quản lý thông qua Spring @Transactional và Hibernate Transaction Manager). Rõ ràng, đó không phải là làm việc, nhưng các lựa chọn thay thế ngoài việc sử dụng setAutoCommit là gì, và tại sao nó sẽ làm việc trong Spring3.0/Hibernate 3.5 nhưng không phải Spring 3.1/Hibernate 4?
Cảm ơn mọi suy nghĩ hoặc đề xuất - chúng tôi đang bối rối.
Cảm ơn bạn rất nhiều, chắc chắn điều này đã giúp tôi tiết kiệm rất nhiều thời gian. –