2016-01-11 16 views
8

Khi gọi một thủ tục Oracle lưu trữ với tham số OracleTypes.ARRAY đầu vào nhiều lần, nhận được lỗi sau: -Xuân StoredProcedure với Oracle mảng: ORA-01.000: con trỏ mở tối đa vượt quá

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] 

Mẫu cấu hình JDBC là: -

<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> 

lớp Thủ tục lưu trữ: -

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

Thay vì CommonsDbcpNativeJdbcExtractor thử với OracleJdbc4NativeJdbcExtractor quá. Nhưng vẫn còn lỗi ở đó.

Về cơ bản, heap chứa rất nhiều đối tượng không được tiết lộ Statement. Bất kỳ ý tưởng tại sao mùa xuân không đóng tài nguyên?

Môi trường: - Java 1.8, Spring 4.1.6, Tomcat 7.

+2

@LalitKumarB Trong khi câu hỏi được liên kết trả lời nguyên nhân cơ bản của lỗi 'ORA-01000' là gì, nó không trả lời câu hỏi mà OP hỏi" Tại sao mùa xuân không đóng tài nguyên? " – MT0

+1

@LalitKumarB Vui lòng không đánh dấu câu hỏi là trùng lặp, mà không đọc nó – Manu

+0

Bài đăng mở lại. Trên một mặt lưu ý, nó sẽ là tốt đẹp nếu bạn có thể chỉnh sửa các câu hỏi và giải thích lý do tại sao nó không phải là một bản sao. –

Trả lời

0

Trong trường hợp trên, vấn đề là do quyền sở hữu sai loại mảng oracle. Trên thực tế, kiểu mảng do người dùng định nghĩa TBL_EMP_ID được sở hữu bởi một lược đồ, khác với lược đồ mà thủ tục đã lưu trữ được khai báo.

Sự cố đã được giải quyết bằng cách di chuyển khai báo loại mảng đến cùng một lược đồ nơi quy trình được lưu trữ GET_EMPLOYEE_LIST được khai báo.

+0

Làm cách nào bạn xác định rằng đó là quyền sở hữu loại mảng oracle đã gây ra sự cố? Theo https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#jdbc Mùa xuân phải đóng các câu lệnh - có lỗi mùa xuân mô tả lý do tại sao không ? – Ryan

+0

Thành thật mà nói, điều này được dựa trên một thử nghiệm và lỗi. Có thể là một thiếu sót trong mã spring-jdbc để đóng kết nối trong kịch bản được mô tả ở trên. – Manu

1

kiểm tra thông số open_cursor của bạn. Tham số này xác định con trỏ tối đa cho phép PER SESSION. Mặc định là 50.

Kiểm tra xem bạn có bị rò rỉ con trỏ hay không. Thông thường, giá trị 200 ~ 300 phải đủ lớn cho người dùng thông thường.

Các vấn đề liên quan