2018-08-29

https://www.cnblogs.com/liunanjava/p/4261242.html

一、概述

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

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

CallableStatement 常用方法:

返回类型方法签名说明

booleanexecute()执行 SQL 语句,如果第一个结果是 ResultSet 对

象,则返回 true;如果第一个结果是更新计数或者没

有结果,则返回 false

voidregisterOutParameter(int parameterIndex,int sqlType)按顺序位置parameterIndex 将OUT 参数注册为

JDBC 类型sqlType,sqlType 为Types 类中的常量

TypegetType(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 [(,, ...)]}

函数:{?= call [(,, ...)]}

如果要调用存储过程,则使用第一种语法,就是开头不带问号的语法,call 后面是过程名,

如果没有参数,可以省略小括号。

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

二、CallableStatement 执行存储过程

2.1、建立基类

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;publicclass BaseDao {

    protected Connection conn;

    protected PreparedStatement ps;

    protected ResultSet rs;


    //建立连接publicboolean 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();

            returnfalse;

        } catch (SQLException e) {

            // TODO Auto-generated catch block            e.printStackTrace();

            returnfalse;

        }

        returntrue;

    }


    //增加,修改,删除publicint executeUpdate(String sql, Object[] params){

        getConnection();

        intupdateRow=0;

        try {

            ps=conn.prepareStatement(sql);

            //填充占位符for(inti=0;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(inti=0;i

                    ps.setObject(i+1, params[i]);

                }

                rs = ps.executeQuery();

            } catch (SQLException e) {

                // TODO Auto-generated catch block                e.printStackTrace();

            }

            return rs;

        }


    // 关闭资源publicboolean closeResource() {

            if(rs!=null){

                try {

                    rs.close();

                } catch (SQLException e) {

                    // TODO Auto-generated catch block                    e.printStackTrace();

                    returnfalse;

                }

            }

            if(ps!=null){

                try {

                    ps.close();

                } catch (SQLException e) {

                    // TODO Auto-generated catch block                    e.printStackTrace();

                    returnfalse;

                }

            }


            if(conn!=null){

                try {

                    conn.close();

                } catch (SQLException e) {

                    // TODO Auto-generated catch block                    e.printStackTrace();

                    returnfalse;

                }

            }

            returntrue;

        }

}

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

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

--查询emp表记录数CREATEORREPLACEPROCEDUREgetEmpCount(v_count OUTNUMBER)ASBEGINSELECTCOUNT(*)INTOv_countFROM emp;END;

调用

//执行不带参但是有返回值的存储过程获取emp表总记录数publicint getTotalCountProc(){

        //定义一个变量来接收结果inttotalCount=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;

    }

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

--根据部门编号和姓名查询人数CREATEORREPLACEPROCEDUREgetEmpCount(v_deptnoNUMBER, v_enameVARCHAR2,v_count OUTNUMBER)ASBEGINSELECTCOUNT(*)INTOv_countFROM empWHEREenameLIKE'%'||v_ename||'%'ANDdeptno=v_deptno;END;

//执行带参带返回值的存储过程publicintgetTotalCountProc1(int deptno,String ename){

        //定义一个变量来接收结果inttotalCount=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;


    }

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

--查询员工所有信息CREATEORREPLACEPROCEDURE emp_cur(emp_cur OUT SYS_REFCURSOR)ASBEGINOPENemp_curFORSELECT*FROM emp;END;

//执行返回值为游标的存储过程 游标名emp_cur

    publicList getempProc1(){

        Listemplist=new ArrayList();

        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()){

                intempno=rs.getInt("empno");                           

                String ename=rs.getString("ename");                     

                String job=rs.getString("job");                       

                intmgr=rs.getInt("mgr");                     

                Date hiredate=rs.getDate("hiredate");                   

                doublesal=rs.getDouble("sal");                       

                doublecomm=rs.getDouble("comm");               

                intdeptno=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;


    }

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

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

三、执行函数

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

CREATEORREPLACEFUNCTIONgetename(v_empnoNUMBER)RETURNVARCHAR2ASv_ename VARCHAR2(20);BEGINSELECTenameINTOv_enameFROMempWHEREempno=v_empno;

  RETURN v_ename;END;

publicvoid 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();

            }


        }       

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335