Я получаю данные из Oracle, используя библиотеки JDBC и ojdbc7.jar
. Мой dataSource
:
<bean id="myDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="url" value="${oracle.url}"/>
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="username" value="${oracle.user}"/>
<property name="password" value="${oracle.password}"/>
<property name="maxTotal" value="20"/>
<property name="maxIdle" value="10"/>
<property name="maxWaitMillis" value="-1"/>
</bean>
Мой код:
public List<Link> getTerminalDevices(final int numbersMonths, final Long initServiceId, final List<Long> switchableServices) throws Exception {
final List<Link> result = new ArrayList<>();
try (final Connection cnn = myDataSource.getConnection();
final OracleCallableStatement stm = cnn.prepareCall(sql).unwrap(OracleCallableStatement.class)) {
stm.setPlsqlIndexTable(1, switchableServices.toArray(), switchableServices.size(), switchableServices.size(), OracleTypes.BIGINT, 0);
stm.registerOutParameter(2, OracleTypes.CURSOR);
stm.setLong(3, initServiceId);
stm.setInt(4, numbersMonths);
stm.execute();
try (final ResultSet rs = stm.getCursor(2)) {
while (rs.next()) {
result.add(new Link()
.id(rs.getLong(1))
.name(rs.getString(2))
.date(rs.getTimestamp(3)));
}
}
} catch (Exception ex) {
throw ex;
}
return result;
}
Этот код запускается в 5 потоках. Иногда, однажды из времени у меня появляется ошибка:
java.sql.SQLException: Closed Resultset: getLong
at oracle.jdbc.driver.GeneratedScrollableResultSet.getLong(GeneratedScrollableResultSet.java:539) ~[ojdbc7.jar:12.1.0.1.0]
Ошибка не является постоянной и проявляется в неясных условиях.
Что не так? Я не понимаю эту ошибку, я правильно обрабатываю соединения, использую ресурсы try-with. Я не могу закрыть набор результатов!
UPDATE
Я провел расследование и обнаружил, что проблема в этой строке:
final OracleCallableStatement stm = cnn.prepareCall(sql).unwrap(OracleCallableStatement.class)
Если я сделаю так:
try (final Connection cnn = oracleDatasource.getConnection();
final CallableStatement originalCs = cnn.prepareCall(sql)) {
OracleCallableStatement stm;
if (originalCs instanceof OracleCallableStatement) {
stm = (OracleCallableStatement) originalCs;
} else {
DelegatingCallableStatement tomcatCs = (DelegatingCallableStatement) originalCs;
stm = (OracleCallableStatement) tomcatCs.getInnermostDelegate();
}
Все работает правильно. У кого есть какие мысли по этому поводу? Почему unwrap
работает неправильно?