存储过程是数据库中一种预编译的SQL语句代码集,类似于Java的方法封装具有很高重用功能。
优点:执行效率高,提高访问速度。
缺点:更换数据库系统时存储过程不兼容。
JDBC API中
CallableStatement接口是唯一处理数据库系统存储过程的通用组件
CallableStatement接口
CallableStatement是PreparedStatement接口的子接口用来操作存储过程,此接口由Connection对象获得其实例
一个小插曲:遇到了一个报错:
java调用存储过程,不允许的操作: Ordinal binding and Named binding cannot be combined!
原因是给过程设置参数信息或取值的时候,不能够同时使用下标和名称来指定对应参数。
PL SQL创建一个存储过程:
create or replace procedure pro_querySubject(stuNumbers IN VARCHAR,subjectName IN VARCHAR,datas OUT sys_refcursor) AS BEGIN OPEN datas FOR select stu.numbers,cla.name,sub.name,sco.scores --查询结果使用系统引用游标类型接收 from students stu inner join score sco on stu.id = sco.stuid inner join subject sub on sco.subid = sub.id inner join classinfo cla on cla.id = stu.cid where sub.name = stuNumbers and stu.numbers = subjectName; END;
在相关Dao类中调用:
/** * 1 在数据库中定义一个存储过程,完成给定班级名称和学号及学科, * 获取此学生此学科成绩所有信息,在应用程序中定义相关方法完成调用此存储过程显示成绩信息。 * @param stuNumbers * @param subjectName * @return */ public List<Map<String,Object>> callProcedure3(String stuNumbers,String subjectName){ List<Map<String,Object>> list = new ArrayList<>(); String procName = "{call pro_querySubject(:stuNumbers,:subjectName,:datas)}"; Connection conn = DataSourceManager.getConnection();//获取数据库连接 CallableStatement call = null; ResultSet rs = null; try { call = conn.prepareCall(procName);//创建CallableStatement对象 /* 注册oralce游标类型,此类型可以封装查询结果 */ call.registerOutParameter("stuNumbers",Types.VARCHAR); call.setString("stuNumbers",stuNumbers); call.registerOutParameter("subjectName",Types.VARCHAR); call.setString("subjectName",subjectName); call.registerOutParameter("datas", oracle.jdbc.OracleTypes.CURSOR); call.execute(); rs = (ResultSet) call.getObject("datas");//获取返回输出类型 while(rs.next()){//遍历结果集封装为对象 Map<String,Object> map = new HashMap<>(); map.put("stuNumber",rs.getString(1)); map.put("className",rs.getString(2)); map.put("subName",rs.getString(3)); map.put("scores",rs.getString(4)); list.add(map); } } catch (SQLException throwables) { throwables.printStackTrace(); } finally { DataSourceManager.close(rs); DataSourceManager.close(call); DataSourceManager.close(conn); } return list; }
最后在测试类中调用输出
List<Map<String,Object>> list4 = new ScoreDao().callProcedure3("流体力学","110380"); for(Map<String,Object> map:list4){ System.out.println(map.get("stuNumber") +" "+map.get("className") +" "+map.get("subName") +" "+map.get("scores") ); }