一、概述

如果想要执行存储过程,我们应该使用 CallableStatement 接口。

CallableStatement 接口继承自PreparedStatement 接口。所以CallableStatement 接口包含有Statement 接口和PreparedStatement 接口定义的全部方法,但是并不是所有的方法我们都要使用,主要使用的方法有这样几个:

CallableStatement 常用方法:

返回类型 方法签名 说明
boolean execute()

执行 SQL 语句,如果第一个结果是 ResultSet 对
象,则返回 true;如果第一个结果是更新计数或者没
有结果,则返回 false

void

registerOutParameter(int parameterIndex,int sqlType)

按顺序位置parameterIndex 将OUT 参数注册为
JDBC 类型sqlType,sqlType 为Types 类中的常量

Type

getType(int parameterIndex)

根据参数的序号获取指定的 JDBC 参数的值。第一
个参数是 1,第二个参数是 2,依此类推

我们可以使用execute()方法来执行存储过程。CallableStatement 为所有的数据库提供了一种统一的标准形式调用存储过程。所以,你将会看到我们使用execute()调用存储过程的语法与在Oracle 中会所有不同。

为了获得存储过程或函数的返回值,我们需要使用 registerOutParameter()方法将返回的参数注册为JDBC 的类型。 registerOutParameter()方法的第一个参数是参数的序号,第一个为1,第二个为2,以此类推。第二个参数需要一个int 值,用来标记JDBC 的类型,我们可以使用java.sql.Types 类中的常量来设置这个参数。比如VARCHAR、DOUBLE 等类型。如果类型不够用,也可以从具体数据库的驱动中寻找合适的类型常量。如果存储过程或函数有返回值,这个方法是必须要调用的,否则无法得到返回值,甚至会发生异常。

CallableStatement 接口中定义了很多get 方法,用于获取存储过程返回的值,根据值的类型不同,你可以使用不同get 方法,比如getInt()、getString()、getDouble()等等。
我们看一下使用CallableStatement 接口执行存储过程和函数的语法格式。

存储过程:{call <procedure-name>[(<arg1>,<arg2>, ...)]}
函数:{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}

如果要调用存储过程,则使用第一种语法,就是开头不带问号的语法,call 后面是过程名,
如果没有参数,可以省略小括号。

如果要调用函数,则使用第二种语法,开头带有一个问号加等号,实际上这个问号就是一个占位符,这个问号总是调用函数的第一个占位符。其它部分与过程的语法相同

二、CallableStatement 执行存储过程

2.1、建立基类

  1. public class BaseDao {
  2. protected Connection conn;
  3. protected PreparedStatement ps;
  4. protected ResultSet rs;
  5. //建立连接
  6. public boolean getConnection(){
  7. String driver=ConfigManager.getInstance().getString("jdbc.driver_class");
  8. String url=ConfigManager.getInstance().getString("jdbc.connection.url");
  9. String username=ConfigManager.getInstance().getString("jdbc.connection.username");
  10. String password=ConfigManager.getInstance().getString("jdbc.connection.password");
  11. try {
  12. Class.forName(driver);
  13. conn=DriverManager.getConnection(url,username, password);
  14. } catch (ClassNotFoundException e) {
  15. e.printStackTrace();
  16. return false;
  17. } catch (SQLException e) {
  18. e.printStackTrace();
  19. return false;
  20. }
  21. return true;
  22. }
  23. //增加,修改,删除
  24. public int executeUpdate(String sql, Object[] params){
  25. getConnection();
  26. int updateRow=0;
  27. try {
  28. ps=conn.prepareStatement(sql);
  29. //填充占位符
  30. for(int i=0;i<params.length;i++){
  31. ps.setObject(i+1, params[i]);
  32. }
  33. updateRow = ps.executeUpdate();
  34. } catch (SQLException e) {
  35. e.printStackTrace();
  36. }
  37. return updateRow;
  38. }
  39. //查询
  40.   public ResultSet executeSQL(String sql, Object[] params){
  41.     getConnection();
  42.       try {
  43.         ps=conn.prepareStatement(sql);
  44.         //填充占位符
  45.         for(int i=0;i<params.length;i++){
  46.           ps.setObject(i+1, params[i]);
  47.         }
  48.         rs = ps.executeQuery();
  49.       } catch (SQLException e) {
  50.         e.printStackTrace();
  51.       }
  52.       return rs;
  53.   }
  54. // 关闭资源
  55.   public boolean closeResource() {
  56.     if(rs!=null){
  57.       try {
  58.         rs.close();
  59.       } catch (SQLException e) {
  60.         e.printStackTrace();
  61.         return false;
  62.         }
  63.       }
  64.     if(ps!=null){
  65.       try {
  66.         ps.close();
  67.       } catch (SQLException e) {
  68.         e.printStackTrace();
  69.         return false;
  70.       }
  71.     }
  72.     if(conn!=null){
  73.       try {
  74.         conn.close();
  75.       } catch (SQLException e) {
  76.         e.printStackTrace();
  77.         return false;
  78.         }
  79.       }
  80.       return true;
  81.     }
  82. }

2.2、执行不带参但是有返回值的存储过程

新建类来继承上面的类也可以继承,下面建立存储过程

  1. --查询emp表记录数
  2. CREATE OR REPLACE PROCEDURE getEmpCount(v_count OUT NUMBER)
  3. AS
  4. BEGIN
  5. SELECT COUNT(*) INTO v_count FROM emp;
  6. END;

调用

  1. //执行不带参但是有返回值的存储过程获取emp表总记录数
  2. public int getTotalCountProc(){
  3.   //定义一个变量来接收结果
  4.   int totalCount=0;
  5.   //声明CallableStatement对象
  6.   CallableStatement proc=null;
  7.   String sql="{call getEmpCount(?)}";
  8.   try {
  9. //建立连接
  10. getConnection();
  11. //CallableStatement对象
  12. proc=conn.prepareCall(sql);
  13. //将数据库对象数据类型注册为java中的类型
  14. proc.registerOutParameter(1, Types.INTEGER);
  15. //执行
  16. proc.execute();
  17. //接收返回值
  18. totalCount=proc.getInt(1);
  19.     } catch (SQLException e) {
  20. e.printStackTrace();
  21.     }
  22.     return totalCount;
  23. }

2.3、执行带参带返回值的存储过程

  1. --根据部门编号和姓名查询人数
  2. CREATE OR REPLACE PROCEDURE getEmpCount(v_deptno NUMBER, v_ename VARCHAR2,v_count OUT NUMBER)
  3. AS
  4. BEGIN
  5. SELECT COUNT(*) INTO v_count FROM emp
  6. WHERE ename LIKE '%'||v_ename||'%' AND deptno=v_deptno;
  7. END;
  1. //执行带参带返回值的存储过程
  2. public int getTotalCountProc1(int deptno,String ename){
  3.   //定义一个变量来接收结果
  4.   int totalCount=0;
  5.   //声明CallableStatement对象
  6.   CallableStatement proc=null;
  7.   String sql="{call getEmpCount(?,?,?)}";
  8.   //建立连接
  9.   getConnection();
  10.   //CallableStatement对象
  11.   try {
  12. proc=conn.prepareCall(sql);
  13. //设置占位符
  14. //Object [] params={deptno,ename};
  15. //只设置输入参数即可
  16. proc.setInt(1, deptno);
  17. proc.setString(2, ename);
  18. //proc.setInt(3, totalCount);
  19. ////将数据库对象数据类型注册为java中的类型,将输出参数转换
  20. proc.registerOutParameter(3, Types.INTEGER);
  21. //执行
  22. proc.execute();
  23. //获取结果
  24. totalCount=proc.getInt(3);
  25.     } catch (SQLException e) {
  26. e.printStackTrace();
  27.     }finally{
  28. this.closeResource();
  29. if(proc!=null){
  30. try {
  31. proc.close();
  32. } catch (SQLException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36.     }
  37.     return totalCount;
  38. }

2.3、执行返回值为游标的存储过程

  1. --查询员工所有信息
  2. CREATE OR REPLACE PROCEDURE emp_cur(emp_cur OUT SYS_REFCURSOR)
  3. AS
  4. BEGIN
  5. OPEN emp_cur FOR SELECT * FROM emp;
  6. END;
  1. //执行返回值为游标的存储过程 游标名emp_cur
  2. public List<Emp> getempProc1(){
  3. List<Emp> emplist=new ArrayList<Emp>();
  4. String sql="{call emp_cur(?) }";
  5. //声明CallableStatement对象
  6. CallableStatement proc=null;
  7. //建立连接
  8. getConnection();
  9. try {
  10. //执行
  11. proc=conn.prepareCall(sql);
  12. //注册类型为数据库游标类型
  13. proc.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
  14. //接收结果集
  15. proc.execute();
  16. //获取结果第一个对象
  17. rs=(ResultSet) proc.getObject(1);
  18. while(rs.next()){
  19. int empno=rs.getInt("empno");
  20. String ename=rs.getString("ename");
  21. String job=rs.getString("job");
  22. int mgr=rs.getInt("mgr");
  23. Date hiredate=rs.getDate("hiredate");
  24. double sal=rs.getDouble("sal");
  25. double comm=rs.getDouble("comm");
  26. int deptno=rs.getInt("deptno");
  27. //声明Emp对象
  28. Emp emp=new Emp();
  29. //将得到的值添加到对象中
  30. emp.setEmpno(empno);
  31. emp.setEname(ename);
  32. emp.setJob(job);
  33. emp.setMgr(mgr);
  34. emp.setHiredate(hiredate);
  35. emp.setSal(sal);
  36. emp.setComm(comm);
  37. emp.setDeptno(deptno);
  38. //将对象添加到集合
  39. emplist.add(emp);
  40. }
  41. } catch (SQLException e) {
  42. e.printStackTrace();
  43. }finally{
  44. this.closeResource();
  45. if(proc!=null){
  46. try {
  47. proc.close();
  48. } catch (SQLException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. }
  53. return emplist;
  54. }

以上看出,需要将输出的参数,和结果注册,输入的参数不要注册,

但输入参数需要设置占位符

三、执行函数

3.1 、函数功能为根据雇员id 返回姓名

  1. CREATE OR REPLACE FUNCTION getename(v_empno NUMBER)
  2. RETURN VARCHAR2
  3. AS
  4. v_ename VARCHAR2(20);
  5. BEGIN
  6. SELECT ename INTO v_ename FROM emp WHERE empno=v_empno;
  7. RETURN v_ename;
  8. END;
  1. public void getenamefun(int empno){
  2. //sql
  3. String ename="";
  4. String sql="{?=call getename(?)}";
  5. CallableStatement fun=null;
  6. getConnection();
  7. try {
  8. fun=conn.prepareCall(sql);
  9. fun.setInt(2, empno);
  10. fun.registerOutParameter(1, Types.VARCHAR);
  11. fun.execute();
  12. ename=fun.getString(1);
  13. System.out.println(ename);
  14. } catch (SQLException e) {
  15. e.printStackTrace();
  16. }
  17.  
  18. }

其它的方法与过程一样,只是多了个返回值类型

原博客链接:http://www.cnblogs.com/liunanjava/p/4261242.html

【转】java调用存储过程和函数的更多相关文章

  1. java调用存储过程和函数

    以对表test进行增,删,改,查进行说明:1.新建表test create table TEST ( TID NUMBER not null, TNAME VARCHAR2(32), TCODE VA ...

  2. Java 调用存储过程、函数

     一.Java调用存储Oracle存储过程 测试用表: --创建用户表 create table USERINFO ( username ) not null, password ) not null ...

  3. JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...

  4. JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    1.PreparedStatement对象 PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单 Statement对象编译SQL语句时, ...

  5. JDBC(13)—JDBC调用存储过程和函数

    步骤: JDBC调用存储过程和函数 步骤: ①:通过Connection对象的prepareCall()方法创建一个CallableStatement对象的实例,在使用Connection对象的pre ...

  6. 转:EF调用存储过程、函数

    EF调用存储过程.函数 2014-04-02 09:12:20|  分类: ORM框架|举报|字号 订阅          一.ef4.1 codeFirst 修改表结构 增加字段等 EF code ...

  7. clob字段的值插入和查询N种方法【包括java调用存储过程传入clob参数】

    import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import jav ...

  8. MySQL学习笔记:调用存储过程或函数报1418错误

    问题 MySQL开启bin-log后,调用存储过程或者函数以及触发器时,会出现错误号为1418的错误: ERROR 1418 (HY000): This function has none of DE ...

  9. Oracle数据库基本操作 (五) —— 使用java调用存储过程

    一.环境准备 登录Oracle数据库scott账号,利用emp进行操作. 1.创建 proc_getyearsal 存储过程 -- 获取指定员工年薪 create or replace procedu ...

随机推荐

  1. php报错 Call to undefined function mb_stripos()

    错误原因 没有mbstring扩展 本文只介绍Linux解决办法 方法一 编译PHP的时候 带上--enable-mbstring参数 方法二 进入PHP源码/ext/mbstring目录 ./con ...

  2. vsftp访问异常

    在LINUX下vsftp建立一个FTP服务器,但通过ftp的命令控制台使用FTP时,ls无法查看目录, 当然更无法上传下载文件了! 出错如下 : ftp> ls 227 Entering Pas ...

  3. HQL中左连接,右连接,内连接

    左连接:left join 如A left join B 即取出A表的所有数据,由on条件关联的B表数据,有则显示,没有则为空: 右连接:right join 如 A right join B 即取出 ...

  4. 盖房子(house)

    盖房子(house) 题目描述 FJ最近得到了面积为n*m的一大块土地,他想在这块土地上建造一所房子,这个房子必须膏形的.但是,这块土地并非十全十美,上面有很多不平坦的地方(也可以叫瑕疵).这些瑕疵十 ...

  5. bLock 回调 就是这么简单!

    转载自:http://blog.csdn.net/mobanchengshuang/article/details/11751671 我们在开发中常常会用到函数回调,你可以用通知来替代回调,但是大多数 ...

  6. js实现input button从不可用变为可用

    有时候明明是些很简单的东西,因为自己的一些大意,可能就在那圈子里一直兜兜转转,好久都绕不出来. 所以我也愿意把这些很简单的愚蠢写出来,与君共享~ 首先大家知道<input>有一个名叫“bu ...

  7. FMDB增删查改

    创建,插入,更新和删除:使用executeUpdate方法,而查询则用executeQuery 1.实例化FMDatabase //paths: ios下Document路径,Document为ios ...

  8. windows矢量字体点阵数据的提取(转)

    源:windows矢量字体点阵数据的提取 问题参考:windows api 获取字库点阵的问题 1.提取原理 在windows系统当中提取矢量字体的字模有很多方法,下面介绍一种利用GetGlyphOu ...

  9. Horizon/DomainWorkFlow

    https://wiki.openstack.org/wiki/Horizon/DomainWorkFlow

  10. 高效判断奇偶性,利用位运算符&

    这种位运算判断奇偶性,在程序和数据库里面都是可以用的 public static bool isOdd(i) { return (i&1)!=0 } 最小奇数是:1   最小偶数是:0   所 ...