У меня проблема с обновлением драйвера JDBC. Я пробовал два разных драйвера
JNetDirects JSQLConnect и драйвер Microsofts показывают одинаковое поведение. При выполнении нескольких подготовленных операторов в неавтоматическом состоянии операторы, кажется, не разделяют состояние сеанса. Это доставляет мне неприятности. Есть ли способ указать соединению, что операторы должны иметь одно и то же состояние сеанса?
Вот пример того, как реплицировать, не разделяя состояние сеанса. Следующий фрагмент выдает исключение в строке insert.execute();
. Исключение, вызванное отключением вставки идентификатора, демонстрирует, что состояние сеанса не поддерживалось между двумя подготовленными операторами.
Connection connection = dataSource.getConnection();
connection.setAutoCommit(false);
PreparedStatement identityON = connection.prepareStatement("SET IDENTITY_INSERT TestStuff ON");
identityON.execute();
identityON.close();
PreparedStatement insert = connection.prepareStatement("INSERT INTO TestStuff (id) VALUES(-1)");
insert.execute(); // Results in Cannot insert explicit value for identity column in table 'TestStuff' when IDENTITY_INSERT is set to OFF.
insert.close();
PreparedStatement identityOFF = connection.prepareStatement("SET IDENTITY_INSERT TestStuff OFF");
identityOFF.execute();
identityOFF.close();
connection.commit();
connection.close();
Создание таблицы:
CREATE TABLE TestStuff (
id int identity(1,1) PRIMARY KEY
,col int
)
При исключении возможных ошибок, я удостоверился, что состояние сеанса не очищается между пакетами
SET IDENTITY_INSERT TestStuff ON:
GO
INSERT INTO TestStuff (id) VALUES(-1);
GO
SET IDENTITY_INSERT TestStuff OFF:
Это будет работать при непосредственном выполнении с экземпляром SQL Server. Демонстрация того, что пакетирование не влияет на объем сеансов.
Другое любопытство заключается в том, что @@ IDENTITY будет выполнять перенос между утверждениями, а SCOPE_IDENTITY () - нет.
PreparedStatement insert = connection.prepareStatement("INSERT INTO TestStuff (Col) VALUES(1)");
insert.execute();
insert.close();
PreparedStatement scoptIdentStatement = connection.prepareStatement("SELECT @@IDENTITY, SCOPE_IDENTITY()");
scoptIdentStatement.execute();
ResultSet scoptIdentRS = scoptIdentStatement.getResultSet();
scoptIdentRS.next();
Short identity = scoptIdentRS.getShort(1);
Short scopeIdent = scoptIdentRS.getShort(2);
PreparedStatement maxIdStatement = connection.prepareStatement("SELECT MAX(id) FROM TestStuff");
maxIdStatement.execute();
ResultSet maxIdRS = maxIdStatement.getResultSet();
maxIdRS.next();
Short actual = maxIdRS.getShort(1);
System.out.println(String.format("Session: %s Scope: %s, Actual: %s", identity, scopeIdent, actual )); // Session: 121 Scope: 0, Actual: 121
Тот же пример в SQL Server и результат:
INSERT INTO TestStuff( col) VALUES (1)
PRINT CONCAT('Session: ', @@IDENTITY, ' Scope: ', SCOPE_IDENTITY() )
-- Session: 122 Scope: 122 (Can't print actual without polluting the output here)