【转】java调用存储过程和函数
一、概述
如果想要执行存储过程,我们应该使用 CallableStatement 接口。
CallableStatement 接口继承自PreparedStatement 接口。所以CallableStatement 接口包含有Statement 接口和PreparedStatement 接口定义的全部方法,但是并不是所有的方法我们都要使用,主要使用的方法有这样几个:
CallableStatement 常用方法:
返回类型 | 方法签名 | 说明 |
boolean | execute() |
执行 SQL 语句,如果第一个结果是 ResultSet 对 |
void |
registerOutParameter(int parameterIndex,int sqlType) |
按顺序位置parameterIndex 将OUT 参数注册为 |
Type |
getType(int parameterIndex) |
根据参数的序号获取指定的 JDBC 参数的值。第一 |
我们可以使用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、建立基类
- 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) {
- e.printStackTrace();
- return false;
- } catch (SQLException e) {
- 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) {
- 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) {
- e.printStackTrace();
- }
- return rs;
- }
- // 关闭资源
- public boolean closeResource() {
- if(rs!=null){
- try {
- rs.close();
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- }
- if(ps!=null){
- try {
- ps.close();
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- }
- if(conn!=null){
- try {
- conn.close();
- } catch (SQLException e) {
- e.printStackTrace();
- return false;
- }
- }
- return true;
- }
- }
2.2、执行不带参但是有返回值的存储过程
新建类来继承上面的类也可以继承,下面建立存储过程
- --查询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) {
- e.printStackTrace();
- }
- return totalCount;
- }
2.3、执行带参带返回值的存储过程
- --根据部门编号和姓名查询人数
- 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) {
- e.printStackTrace();
- }finally{
- this.closeResource();
- if(proc!=null){
- try {
- proc.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- return totalCount;
- }
2.3、执行返回值为游标的存储过程
- --查询员工所有信息
- 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) {
- e.printStackTrace();
- }finally{
- this.closeResource();
- if(proc!=null){
- try {
- proc.close();
- } catch (SQLException e) {
- e.printStackTrace();
- }
- }
- }
- return emplist;
- }
以上看出,需要将输出的参数,和结果注册,输入的参数不要注册,
但输入参数需要设置占位符
三、执行函数
3.1 、函数功能为根据雇员id 返回姓名
- 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) {
- e.printStackTrace();
- }
- }
其它的方法与过程一样,只是多了个返回值类型
原博客链接:http://www.cnblogs.com/liunanjava/p/4261242.html
【转】java调用存储过程和函数的更多相关文章
- java调用存储过程和函数
以对表test进行增,删,改,查进行说明:1.新建表test create table TEST ( TID NUMBER not null, TNAME VARCHAR2(32), TCODE VA ...
- Java 调用存储过程、函数
一.Java调用存储Oracle存储过程 测试用表: --创建用户表 create table USERINFO ( username ) not null, password ) not null ...
- JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】
这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...
- JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】
1.PreparedStatement对象 PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单 Statement对象编译SQL语句时, ...
- JDBC(13)—JDBC调用存储过程和函数
步骤: JDBC调用存储过程和函数 步骤: ①:通过Connection对象的prepareCall()方法创建一个CallableStatement对象的实例,在使用Connection对象的pre ...
- 转:EF调用存储过程、函数
EF调用存储过程.函数 2014-04-02 09:12:20| 分类: ORM框架|举报|字号 订阅 一.ef4.1 codeFirst 修改表结构 增加字段等 EF code ...
- clob字段的值插入和查询N种方法【包括java调用存储过程传入clob参数】
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import jav ...
- MySQL学习笔记:调用存储过程或函数报1418错误
问题 MySQL开启bin-log后,调用存储过程或者函数以及触发器时,会出现错误号为1418的错误: ERROR 1418 (HY000): This function has none of DE ...
- Oracle数据库基本操作 (五) —— 使用java调用存储过程
一.环境准备 登录Oracle数据库scott账号,利用emp进行操作. 1.创建 proc_getyearsal 存储过程 -- 获取指定员工年薪 create or replace procedu ...
随机推荐
- zabbix企业应用之bind dns监控(转)
继续介绍zabbix监控企业应用的实例,本次介绍zabbix监控dns,我监控的dns为bind 9.8.2,本dns为公网dns,是为了解决公司内网服务器自动化所需求的dns解析,比如目前的pupp ...
- AIM Tech Round 3 (Div. 2) B 数学+贪心
http://codeforces.com/contest/709 题目大意:给一个一维的坐标轴,上面有n个点,我们刚开始在位置a,问,从a点开始走,走n-1个点所需要的最小路程. 思路:我们知道,如 ...
- FACE++学习一、detect接口
/detection/detect 描述 检测给定图片(Image)中的所有人脸(Face)的位置和相应的面部属性 目前面部属性包括性别(gender), 年龄(age), 种族(race), 微笑程 ...
- CocoaPods安装和使用及问题----看过写的最好的
目录 CocoaPods是什么? 如何下载和安装CocoaPods? 如何使用CocoaPods? 场景1:利用CocoaPods,在项目中导入AFNetworking类库 场景2:如何正确编译运行一 ...
- 程序员 10Tips
理解技术债务 技术债务就像信用卡一样,会有很高的利息率,时间越长,修复所花的代价就越大,程序员对这个要有深刻的认识.同时团队应该培养一种保证设计质量的文化,应当鼓励重构.同时也应当鼓励其它有关代码质量 ...
- JAVA基础-多态
多态 polymophism: 动态绑定, 迟绑定, 指在执行期间(java), 而不是编译期间(javac), 判断所引用对象的实际类型, 根据实际类型调用响应的方法. 3个条件: 1. 继承 2. ...
- vm10虚拟机安装Mac OS X10.10教程
VM10装Mac OS X 10.9.3及更新到Mac OS X 10.10,让你的windows也能玩Swift . 最近WWDC放出终极大招——新的编程语言Swift(雨燕),导致一大波程序员的 ...
- 在XAMPP上建立多个域名的站点
XAMPP默认安装完毕后,站点文件默认放在/xampp/htdocs/ 文件下,并且可以通过http://localhost 进行访问.先前在测试各种程序的时候均是在/xampp/htdocs/ 文件 ...
- CodeForces 617C Watering Flowers
无脑暴力题,算出所有点到圆心p1的距离的平方,从小到大排序. 然后暴力枚举p1的半径的平方,计算剩余点中到p2的最大距离的平方,枚举过程中记录答案 #include<cstdio> #in ...
- SpingMvc 注解的使用
1.使用注解减少配置xml文件 2.注解可以降低耦合度 3.使用注解编写的普通类 import javax.servlet.http.HttpServletRequest; import org.sp ...