JDBC Prepared Statement对会话范围感到困惑

时间:2018-05-10 22:47:43

标签: java sql tsql jdbc prepared-statement

升级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)

0 个答案:

没有答案