若是想要执行存储过程,咱们应该使用 CallableStatement 接口。html
CallableStatement 接口继承自PreparedStatement 接口。因此CallableStatement 接口包含有Statement 接口和PreparedStatement 接口定义的所有方法,可是并非全部的方法咱们都要使用,主要使用的方法有这样几个:java
CallableStatement 经常使用方法:sql
返回类型 | 方法签名 | 说明 |
boolean | execute() | 执行 SQL 语句,若是第一个结果是 ResultSet 对 象,则返回 true;若是第一个结果是更新计数或者没 有结果,则返回 false数据库 |
void | registerOutParameter(int parameterIndex,int sqlType)oracle |
按顺序位置parameterIndex 将OUT 参数注册为 JDBC 类型sqlType,sqlType 为Types 类中的常量函数 |
Type | getType(int parameterIndex)this |
根据参数的序号获取指定的 JDBC 参数的值。第一 个参数是 1,第二个参数是 2,依此类推url |
咱们可使用execute()方法来执行存储过程。CallableStatement 为全部的数据库提供了一种统一的标准形式调用存储过程。因此,你将会看到咱们使用execute()调用存储过程的语法与在Oracle 中会全部不一样。spa
为了得到存储过程或函数的返回值,咱们须要使用 registerOutParameter()方法将返回的参数注册为JDBC 的类型。 registerOutParameter()方法的第一个参数是参数的序号,第一个为1,第二个为2,以此类推。第二个参数须要一个int 值,用来标记JDBC 的类型,咱们可使用java.sql.Types 类中的常量来设置这个参数。好比VARCHAR、DOUBLE 等类型。若是类型不够用,也能够从具体数据库的驱动中寻找合适的类型常量。若是存储过程或函数有返回值,这个方法是必需要调用的,不然没法获得返回值,甚至会发生异常。code
CallableStatement 接口中定义了不少get 方法,用于获取存储过程返回的值,根据值的类型不一样,你可使用不一样get 方法,好比getInt()、getString()、getDouble()等等。 咱们看一下使用CallableStatement 接口执行存储过程和函数的语法格式。
存储过程:{call <procedure-name>[(<arg1>,<arg2>, ...)]} 函数:{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
若是要调用存储过程,则使用第一种语法,就是开头不带问号的语法,call 后面是过程名, 若是没有参数,能够省略小括号。
若是要调用函数,则使用第二种语法,开头带有一个问号加等号,实际上这个问号就是一个占位符,这个问号老是调用函数的第一个占位符。其它部分与过程的语法相同
package com.pb.emp.dao; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import com.pb.emp.untily.ConfigManager; public class BaseDao { protected Connection conn; protected PreparedStatement ps; protected ResultSet rs; //创建链接 public boolean getConnection(){ String driver=ConfigManager.getInstance().getString("jdbc.driver_class"); String url=ConfigManager.getInstance().getString("jdbc.connection.url"); String username=ConfigManager.getInstance().getString("jdbc.connection.username"); String password=ConfigManager.getInstance().getString("jdbc.connection.password"); try { Class.forName(driver); conn=DriverManager.getConnection(url,username, password); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } return true; } //增长,修改,删除 public int executeUpdate(String sql, Object[] params){ getConnection(); int updateRow=0; try { ps=conn.prepareStatement(sql); //填充占位符 for(int i=0;i<params.length;i++){ ps.setObject(i+1, params[i]); } updateRow = ps.executeUpdate(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return updateRow; } // //查询 public ResultSet executeSQL(String sql, Object[] params){ getConnection(); try { ps=conn.prepareStatement(sql); //填充占位符 for(int i=0;i<params.length;i++){ ps.setObject(i+1, params[i]); } rs = ps.executeQuery(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return rs; } // 关闭资源 public boolean closeResource() { if(rs!=null){ try { rs.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return false; } } return true; } }
新建类来继承上面的类也能够继承,下面创建存储过程
--查询emp表记录数 CREATE OR REPLACE PROCEDURE getEmpCount(v_count OUT NUMBER) AS BEGIN SELECT COUNT(*) INTO v_count FROM emp; END;
调用
//执行不带参可是有返回值的存储过程获取emp表总记录数 public int getTotalCountProc(){ //定义一个变量来接收结果 int totalCount=0; //声明CallableStatement对象 CallableStatement proc=null; String sql="{call getEmpCount(?)}"; try { //创建链接 getConnection(); //CallableStatement对象 proc=conn.prepareCall(sql); //将数据库对象数据类型注册为java中的类型 proc.registerOutParameter(1, Types.INTEGER); //执行 proc.execute(); //接收返回值 totalCount=proc.getInt(1); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return totalCount; }
--根据部门编号和姓名查询人数 CREATE OR REPLACE PROCEDURE getEmpCount(v_deptno NUMBER, v_ename VARCHAR2,v_count OUT NUMBER) AS BEGIN SELECT COUNT(*) INTO v_count FROM emp WHERE ename LIKE '%'||v_ename||'%' AND deptno=v_deptno; END;
//执行带参带返回值的存储过程 public int getTotalCountProc1(int deptno,String ename){ //定义一个变量来接收结果 int totalCount=0; //声明CallableStatement对象 CallableStatement proc=null; String sql="{call getEmpCount(?,?,?)}"; //创建链接 getConnection(); //CallableStatement对象 try { proc=conn.prepareCall(sql); //设置占位符 //Object [] params={deptno,ename}; //只设置输入参数便可 proc.setInt(1, deptno); proc.setString(2, ename); //proc.setInt(3, totalCount); ////将数据库对象数据类型注册为java中的类型,将输出参数转换 proc.registerOutParameter(3, Types.INTEGER); //执行 proc.execute(); //获取结果 totalCount=proc.getInt(3); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ this.closeResource(); if(proc!=null){ try { proc.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return totalCount; }
--查询员工全部信息 CREATE OR REPLACE PROCEDURE emp_cur(emp_cur OUT SYS_REFCURSOR) AS BEGIN OPEN emp_cur FOR SELECT * FROM emp; END;
//执行返回值为游标的存储过程 游标名emp_cur public List<Emp> getempProc1(){ List<Emp> emplist=new ArrayList<Emp>(); String sql="{call emp_cur(?) }"; //声明CallableStatement对象 CallableStatement proc=null; //创建链接 getConnection(); try { //执行 proc=conn.prepareCall(sql); //注册类型为数据库游标类型 proc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR); //接收结果集 proc.execute(); //获取结果第一个对象 rs=(ResultSet) proc.getObject(1); while(rs.next()){ int empno=rs.getInt("empno"); String ename=rs.getString("ename"); String job=rs.getString("job"); int mgr=rs.getInt("mgr"); Date hiredate=rs.getDate("hiredate"); double sal=rs.getDouble("sal"); double comm=rs.getDouble("comm"); int deptno=rs.getInt("deptno"); //声明Emp对象 Emp emp=new Emp(); //将获得的值添加到对象中 emp.setEmpno(empno); emp.setEname(ename); emp.setJob(job); emp.setMgr(mgr); emp.setHiredate(hiredate); emp.setSal(sal); emp.setComm(comm); emp.setDeptno(deptno); //将对象添加到集合 emplist.add(emp); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ this.closeResource(); if(proc!=null){ try { proc.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return emplist; }
以上看出,须要将输出的参数,和结果注册,输入的参数不要注册,
但输入参数须要设置占位符
CREATE OR REPLACE FUNCTION getename(v_empno NUMBER) RETURN VARCHAR2 AS v_ename VARCHAR2(20); BEGIN SELECT ename INTO v_ename FROM emp WHERE empno=v_empno; RETURN v_ename; END;
public void getenamefun(int empno){ //sql String ename=""; String sql="{?=call getename(?)}"; CallableStatement fun=null; getConnection(); try { fun=conn.prepareCall(sql); fun.setInt(2, empno); fun.registerOutParameter(1, Types.VARCHAR); fun.execute(); ename=fun.getString(1); System.out.println(ename); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
其它的方法与过程同样,只是多了个返回值类型