Java 使用Oracle阵列的Spring Stored过程:ORA-01000:超过最大打开游标数

Java 使用Oracle阵列的Spring Stored过程:ORA-01000:超过最大打开游标数,java,oracle,stored-procedures,spring-jdbc,Java,Oracle,Stored Procedures,Spring Jdbc,使用OracleTypes.ARRAY输入参数多次调用Oracle存储过程时,出现以下错误:- org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{call EMP_SCHEMA.GET_EMPLOYEE_LIST(?, ?)}]; SQL state [72000]; error code [1000]; ORA-0

使用
OracleTypes.ARRAY
输入参数多次调用Oracle存储过程时,出现以下错误:-

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>
而不是使用
OracleJdbc4NativeJdbcExtractor
尝试使用
CommonDBCPNativeJDBCExtractor
。但错误仍然存在

基本上,堆包含许多未关闭的
语句
对象。知道spring为什么不关闭资源吗


环境:-Java 1.8、Spring 4.1.6、Tomcat 7。

在上述情况下,问题是由于oracle阵列类型的所有权错误。实际上,用户定义的数组类型
TBL_EMP_ID
属于一个模式,而不是声明存储过程的模式


通过将数组类型声明移动到声明存储过程
GET\u EMPLOYEE\u LIST
的同一架构,问题得以解决。

检查open\u cursor参数。此参数定义每个会话允许的最大游标数。默认值为50


检查是否有任何光标泄漏。正常情况下,200~300的值对于普通用户来说已经足够了

@LalitKumarB虽然链接的问题确实回答了
ORA-01000
错误的根本原因是什么,但它没有回答OP提出的问题,即“为什么spring没有关闭资源?”@LalitKumarB请不要将问题标记为重复,而不要阅读重新打开的itPost。顺便说一句,如果你能编辑这个问题,并解释为什么它不是重复的,那就太好了。@kmmanu为什么有人甚至不看就把一篇文章标记为重复的?根本问题正是标记为重复的帖子中的答案。如果你能编辑这个问题并解释为什么它不是重复的,那就太好了。@LalitKumarB感谢你重新打开这篇文章。潜在的问题可能是相同的。但问题是为什么Spring在使用框架提供的API时无法关闭JDBC资源。您如何确定是oracle阵列类型的所有权造成了问题?根据Spring的说法,应该结束这些陈述——是否有一个Spring bug描述了为什么没有?坦率地说,这是基于一次尝试和错误。在上述场景中,关闭连接可能是SpringJDBC代码中的一个缺点。
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);
  }
}
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);
  }
}