Я пытаюсь создать временную таблицу - #EMPLOYEE_TABLE
в базе данных MSSQL, используя Spring и пул соединений DBCP2. Я использую java.sql.Statement
для выполнения выполнения на БД. Я закрываю соединение после выполнения, чтобы отправить его обратно в пул соединений. Этот процесс создания отлично работает для первого выполнения. Но для последующего выполнения выдает следующую ошибку:
com.microsoft.sqlserver.jdbc.SQLServerException: There is already an object named '#EMPLOYEE_TABLE' in the database.12:26:37.852 [34mINFO [0;39m [35mcom.lex.dbcp.dao.TestDaoImpl[0;39m - Connection :>>org.apache.commons.dbcp2.PoolingDataSource$PoolGuardConnectionWrapper@1807f5a7
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:215)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1635)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.doExecuteStatement(SQLServerStatement.java:865)
at com.microsoft.sqlserver.jdbc.SQLServerStatement$StmtExecCmd.doExecute(SQLServerStatement.java:762)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5846)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1719)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:184)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:159)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.execute(SQLServerStatement.java:735)
at org.apache.commons.dbcp2.DelegatingStatement.execute(DelegatingStatement.java:175)
at org.apache.commons.dbcp2.DelegatingStatement.execute(DelegatingStatement.java:175)
at org.apache.commons.dbcp2.DelegatingStatement.execute(DelegatingStatement.java:175)
at com.lex.dbcp.dao.TestDaoImpl.createTempTableUsingStatement(TestDaoImpl.java:131)
at com.lex.dbcp.common.App.main(App.java:25)
Это БД MSSQL 2014, версия DBCP2 - 2.6.0, и я запускаю ее на Java 1.8
Однако, если я изменю реализацию execute с java.sql.Statement
на java.sql.PreparedStatement
, выполнение будет работать нормально при любом количестве срабатываний.
Пример кода для использования интерфейса Statement:
public void createTempTableUsingStatement() {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
String sqlQuery = "SELECT * INTO #EMPLOYEE_TABLE FROM EMPLOYEE WHERE 1=2";
try {
conn = jdbcTemplate.getDataSource().getConnection();
st = conn.createStatement();
st.execute(sqlQuery);
LOGGER.info("Table created");
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != st) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Пример кода с использованием PreparedStatement
public void createTempTableUsingPreparedStatement() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sqlQuery = "SELECT * INTO #EMPLOYEE_TABLE FROM EMPLOYEE WHERE 1=2";
try {
conn = jdbcTemplate.getDataSource().getConnection();
ps = conn.prepareStatement(sqlQuery);
ps.execute();
LOGGER.info("Table created");
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Структура таблицы
CREATE TABLE EMPLOYEE(
emp_id int identity,
emp_name varchar(255)
);
Я оставил копию исходного проекта для справки здесь StandAlone
Теперь я хотел бы понять, почему создание временной таблицы для многократного запуска работает в случае java.sql.PreparedStatement
, а не в java.sql.Statement
. Я также использовал try with resources
, чтобы увидеть, была ли проблема в освобождении ресурсов, и получил тот же результат.
Я что-то упускаю? Может кто-нибудь помочь мне разобраться в этом поведении?