Spring StoredProcedure с массивом Oracle: ORA-01000: превышены максимальные открытые курсоры

При вызове хранимой процедуры Oracle с параметром ввода OracleTypes.ARRAY несколько раз, получив следующую ошибку: -

org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call EMP_SCHEMA.GET_EMPLOYEE_LIST(?, ?)}]; SQL state [72000]; error code [1000]; ORA-01000: maximum open cursors exceeded; nested exception is java.sql.SQLException: ORA-01000: maximum open cursors exceeded
            at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:84) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
            at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81) ~[spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]

Конфигурация шаблона JDBC: -

    <bean id="commonsDbcpNativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <constructor-arg>
        <ref bean="dataSource" />
    </constructor-arg>
    <property name="nativeJdbcExtractor" ref="commonsDbcpNativeJdbcExtractor" />
</bean>

Сохраненный класс процедуры: -

public class GetEmployees extends StoredProcedure {
  public GetEmployees(JdbcTemplate jdbcTemplate) {
    super(jdbcTemplate, "EMP_SCHEMA.GET_EMPLOYEE_LIST");
    declareParameter(new SqlParameter("p_emp_id_list", OracleTypes.ARRAY, "TBL_EMP_ID"));
    declareParameter(new SqlOutParameter(CURSOR, OracleTypes.CURSOR, new EmployeeDataRowMapper()));
    compile();
  }

  public List<Employee> ofIds(Set<EmployeeId> employeeIds) {
    Map<String, OracleArraySqlTypeValue> params = new HashMap<>();
    params.put("p_emp_id_list", new OracleArraySqlTypeValue(employeeIds));
    final Map<String, Object> result = execute(params);

    return (List<Employee>) result.get(CURSOR);
  }
}

Oracle SqlTypeValue: -

public class OracleArraySqlTypeValue extends AbstractSqlTypeValue {
  private final String[][] employeeIds;

  public OracleArraySqlTypeValue(String[][] employeeIds) {
    this.employeeIds = employeeIds;
  }

  @Override
  protected Object createTypeValue(Connection connection, int sqlType, String typeName) throws SQLException {
    ArrayDescriptor arrayDescriptor = new ArrayDescriptor(typeName, connection);
    return new ARRAY(arrayDescriptor, connection, employeeIds);
  }
}

Вместо CommonsDbcpNativeJdbcExtractor попробовал с OracleJdbc4NativeJdbcExtractor тоже. Но все же ошибка есть.

В основном куча содержит много незакрытых объектов Statement. Любая идея, почему spring не закрывает ресурсы?

Окружающая среда: - Java 1.8, spring 4.1.6, Tomcat 7.

Ответ 1

проверьте свой параметр open_cursor. Этот параметр определяет максимальный курсор, разрешенный PER SESSION. Значение по умолчанию - 50.

Проверьте, нет ли утечки курсора. Обычно для обычных пользователей значение 200 ~ 300 должно быть более чем достаточно.

Ответ 2

В приведенном выше случае проблема возникла из-за неправильного владения типом массива oracle. Фактически определяемый пользователем тип массива TBL_EMP_ID принадлежал схеме, отличной от схемы, в которой была объявлена ​​хранимая процедура.

Проблема была решена путем перемещения объявления типа массива в ту же схему, где была объявлена ​​хранимая процедура GET_EMPLOYEE_LIST.