2016-01-11 53 views
8

Quando si chiama una stored procedure Oracle con parametri OracleTypes.ARRAY ingresso più volte, ottenendo il seguente errore: -primavera StoredProcedure con Oracle matrice: ORA-01000: massimo cursori aperti superato

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] 

La configurazione del modello 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> 

La classe di stored procedure: -

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); 
    } 
} 

Invece di CommonsDbcpNativeJdbcExtractor provato con OracleJdbc4NativeJdbcExtractor troppo. Ma ancora l'errore è lì.

Fondamentalmente lo heap contiene molti oggetti non chiusi Statement. Qualche idea sul perché la primavera non stia chiudendo le risorse?

Ambiente: - Java 1.8, Primavera 4.1.6, Tomcat 7.

+2

@LalitKumarB Mentre la domanda collegata risponde a quale causa sottostante l'errore 'ORA-01000', esso non risponde alla domanda che l'OP ha chiesto quale era" Perché la molla non chiude le risorse? " – MT0

+1

@LalitKumarB Si prega di non contrassegnare le domande come duplicate, senza leggerle – Manu

+0

Dopo la riapertura. Una nota a margine, sarebbe bello se tu potessi modificare la domanda e spiegare perché non è un duplicato. –

risposta

0

Nel caso di cui sopra, il problema è dovuto alla proprietà sbagliato di tipo array oracolo. In realtà il tipo di array definito dall'utente TBL_EMP_ID era di proprietà di uno schema, diverso dallo schema in cui è stata dichiarata la stored procedure.

Il problema è stato risolto spostando la dichiarazione del tipo di matrice sullo stesso schema in cui è stata dichiarata la stored procedure GET_EMPLOYEE_LIST.

+0

Come è stato determinato che era la proprietà del tipo di array Oracle che causava il problema? Secondo https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#jdbc Spring dovrebbe chiudere le dichiarazioni - c'è un bug di primavera che descrive il motivo per cui non è stato ? – Ryan

+0

Francamente, questo era basato su una prova ed errore. Potrebbe essere una lacuna nel codice jdbc spring per chiudere la connessione nello scenario sopra descritto. – Manu

1

controllare il parametro open_cursor. Questo parametro definisce il cursore massimo consentito PER SESSIONE. L'impostazione predefinita è 50.

Verificare se è presente una perdita di cursore. Normalmente un valore di 200 ~ 300 dovrebbe essere più che sufficiente per gli utenti regolari.