Подготовленное заявление JDBC Смущает область действия сеанса - PullRequest
0 голосов
/ 11 мая 2018

У меня проблема с обновлением драйвера 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)

1 Ответ

0 голосов
/ 11 мая 2018

Если вы измените PreparedStatement на Statement для IDENTITY_INSERT, тогда это будет работать так, как вы намереваетесь

Statement identityON = connection.createStatement();
identityON.execute("SET IDENTITY_INSERT TestStuff ON");
identityON.close();

Также обратите внимание на документы :

SCOPE_IDENTITY: возвращает последнее значение идентификатора, вставленное в столбец идентификатора в той же области.Область действия - это модуль: хранимая процедура, триггер, функция или пакет.Поэтому, если два оператора находятся в одной и той же хранимой процедуре, функции или пакете, они находятся в одной и той же области видимости.

и

SCOPE_IDENTITY и @@ IDENTITY возвращаютпоследние значения идентичности, которые генерируются в любой таблице в текущем сеансе.Однако SCOPE_IDENTITY возвращает значения, вставленные только в текущую область;@@ IDENTITY не ограничивается конкретной областью действия.

Отсюда и отличающиеся значения от Management studio и от драйвера JDBC.

...