Oracle 存储过程返回数组记录集

 

刚学,耗了两天调试,寒一个。

  1. 存储过程:


--创建返回对象类型
CREATE TYPE T_DEPT_NUM_O1 AS OBJECT(
dept_id NUMBER ,
num NUMBER
);
/
--创建临时表
CREATE type T_DEPT_NUM_T1 as table of T_DEPT_NUM_O1;
/
--创建包
CREATE OR REPLACE PACKAGE KPI_DEPT_EMP_COUNT1 AS



PROCEDURE EmployeeCountProcedure1
(
emp_count out T_DEPT_NUM_T1 --定义返回为临时表类型
);
end KPI_DEPT_EMP_COUNT1;
/
SHOW ERRORS
/
--创建包体
CREATE OR REPLACE PACKAGE BODY KPI_DEPT_EMP_COUNT1
AS
PROCEDURE EmployeeCountProcedure1 (
emp_count out T_DEPT_NUM_T1
)
IS
deptid number;
i number default 1;
empcount number;

--取得所有有效的部门
cursor c_emp is select sys_org_dept.f_id from sys_org_dept left join sys_org_element on sys_org_element.f_id = sys_org_dept.f_id
where f_isavailable=1 and f_isbusiness = 1;

BEGIN
emp_count := T_DEPT_NUM_T1(); --实例对象
open c_emp;
loop
fetch c_emp into deptid;
if c_emp%notfound then

DBMS_OUTPUT.PUT('======not found=======');
end if;
exit when c_emp%notfound;
--递归查询部门下的所有人数
select to_number(count(*)) into empcount from sys_org_element
where sys_org_element.f_orgtype=8 and f_isavailable=1 and f_isbusiness = 1
start with f_id = deptid connect by prior f_id = f_parentdeptid
;
emp_count.extend; --扩展临时表 表里面放自定义对象
emp_count(i) := T_DEPT_NUM_O1(deptid,empcount);

DBMS_OUTPUT.PUT('the gains that DEPT_ID:');
DBMS_OUTPUT.PUT(deptid);
DBMS_OUTPUT.PUT(' NUM:');
DBMS_OUTPUT.PUT(empcount);
dbms_output.new_line();

i := i + 1;
end loop;
close c_emp; 

END EmployeeCountProcedure1;
END KPI_DEPT_EMP_COUNT1;
/
SHOW ERRORS
/
 

2.sqlplus验证

SET SERVEROUTPUT ON;
--查看结果
declare

emp_count T_DEPT_NUM_T1 := T_DEPT_NUM_T1();
begin
KPI_DEPT_EMP_COUNT1.EmployeeCountProcedure1(emp_count);
end;
/
SHOW ERRORS
/

3.spring中调用存储过程

private class DepartmentEmployeeCountProcedure extends StoredProcedure {

public DepartmentEmployeeCountProcedure(DataSource ds) {
setDataSource(ds);
setJdbcTemplate(new JdbcTemplate(ds));
getJdbcTemplate().setNativeJdbcExtractor(nativeJdbcExtractor);
setSql(PROC_NAME);

declareParameter(new SqlOutParameter("emp_count",Types.ARRAY, "T_DEPT_NUM_T1"));
compile();
}

public Map execute() {
Map out = new HashMap();
try {
Map result = new HashMap();
result = execute(new HashMap());
ARRAY arr = (ARRAY) result.get("emp_count");
ResultSet rs = arr.getResultSet();
while (rs.next()){
STRUCT struct = (STRUCT)rs.getObject(2);
Object[] obs = struct.getAttributes();
out.put(obs[0].toString(),new Double(((BigDecimal)obs[1]).doubleValue()));
System.out.println(obs[0] + " " +obs[0].getClass());
System.out.println(obs[1] + " " +obs[1].getClass());
}
} catch (CannotGetJdbcConnectionException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

return out;
}

}

4.调试过程出现的错误:

  • 内部错误: Image is a collection image, expecting ADT
    有人说是Oracle9的bug,删除所有类型并将使用的类型重新改名就好了,可是我照做了也还是不行,后来添加了方法: setJdbcTemplate(new JdbcTemplate(ds));
    getJdbcTemplate().setNativeJdbcExtractor(nativeJdbcExtractor);
    并修改了返回类型为:Types.ARRAY(原来使用 OracleTypes.STRUCT)就行了。不过这时候我的使用类型名称也已经改掉了。
  • java.lang.AbstractMethodError: oracle.jdbc.driver.OracleConnection.getTypeMap()Ljava/util/Map;
    不知道原因的错误,出现在定义数据库类型时。定义数据库返回类型的变量如下:
    SqlReturnType param = new SqlReturnType() {

    public Object getTypeValue(CallableStatement cs, int paramIndex,
    int sqlType, String typeName) throws SQLException {
    Connection con = cs.getConnection();
    oracle.jdbc.driver.OracleConnection connection = (oracle.jdbc.driver.OracleConnection)con;

    Dictionary d = connection.getTypeMap();
    // if((con instanceof oracle.jdbc.driver.OracleConnection)){
    // con = nativeJdbcExtractor.getNativeConnection(con);
    // System.out.println("=================================");
    // }
    // Map typeMap = con.getTypeMap();
    d.put(typeName, PersonCount.class);
    Object o = cs.getObject(paramIndex);
    return o;
    }

    };
    在不管是使用Connection还是使用OracleConnection,在调用getTypeMap()时总会出现此错误。使用nativeJdbcExtractor获得的连接不会出现此错误,不过好像类型转换无效,取到的结果还是原来的ARRAY里面包含STRUCT对象。

5.调试时一些参考资料:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值