Java中执行存储过程和函数
装载于:http://www.cnblogs.com/liunanjava/p/4261242.html
一、概述
如果想要执行存储过程,我们应该使用 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、建立基类

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;
}
}

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) {
// TODO Auto-generated catch block
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) {
// 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、执行返回值为游标的存储过程
--查询员工所有信息
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; }

以上看出,需要将输出的参数,和结果注册,输入的参数不要注册,
但输入参数需要设置占位符
三、执行函数
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

其它的方法与过程一样,只是多了个返回值类型
Java中执行存储过程和函数的更多相关文章
- Java中执行存储过程和函数(web基础学习笔记十四)
一.概述 如果想要执行存储过程,我们应该使用 CallableStatement 接口. CallableStatement 接口继承自PreparedStatement 接口.所以CallableS ...
- Java中调用存储过程或函数
//?代表一个参数,多个参数用逗号隔开 CallableStatement cs = connect.prepareCall("{?=call 存储过程名称或函数名(?)}"); ...
- Oracle数据库中调用Java类开发存储过程、函数的方法
Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日 浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL, ...
- oracle 包,函数,过程,块的创建和执行及在java中执行(转)
SQL> create or replace procedure sp_guocheng1 is--如果有这个名字就替换 2 begin--执行部分 3 insert into guoc ...
- MyBatis中调用存储过程和函数
一.调用存储过程 1.首先在数据库中定义存储过程,定义的存储过程的代码如下: //定义存储过程 create or replace procedure pag_add(p1 varchar2,p2 v ...
- java中执行js代码
要在java中执行js代码,首先明白,java不支持浏览器本身的方法.支持自定义的js方法,否则会报错 先新建一个js文件:jsss.js 内容如下: function aa(a,b){ return ...
- SQL中的存储过程和函数
存储过程和函数 简单的说,存储过程就是一条或者多条SQL语句的集合.可以视为批文件,但是其作用不仅仅局限于批处理.本文主要介绍如 ...
- Java中执行shell笔记
在java中执行shell有好几种方式:第一种(exec)方式一 public static synchronized void runshell2() { File superuser = n ...
- JAVA中的内联函数
在说内联函数之前,先说说函数的调用过程. 调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到 转去执行该函数前的地方.这种转移操作要求在转去前要保护 ...
随机推荐
- canvas图片跨域问题
canvas的drawImage使用跨域图片时候,会报错,解决方法如下: 1. 使用base64替换跨域图片 如果图片不大,且只有几张,可以使用base64,来代替跨域引用图片. 2. 设置image ...
- 洛谷P1175 表达式的转换
P1175 表达式的转换 44通过 147提交 题目提供者该用户不存在 标签云端 难度提高+/省选- 时空限制1s / 128MB 提交 讨论 题解 最新讨论更多讨论 这题有毒 抄题解棒责五十! ...
- DFA Minimization
有点晚了我就不调试了..不过说是这么说我还是过了编译的.. #include<bits/stdc++.h> using namespace std; namespace DFA{ cons ...
- 【Docker】win10环境下安装Docker
一.进入Docker官网 首先先到Docker官网下载最新官方Docker for Windows:Docker下载 在官网内可以查看到Docker的开发文档. 根据官网提示,Windows环境下下载 ...
- js scrollTop, 滚动条操作
设置页面加载时滚动条自动滚到底的方法: jQuery: 复制代码 代码如下: $(function(){ var h = $(document).height()-$(window).height() ...
- [LeetCode] Surrounded Regions 广度搜索
Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...
- 插入排序Insertion sort(转)
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内 ...
- MSP430G2553头文件解析
MSP430寄存器中文注释---P1/2口(带中断功能) /************************************************************ ...
- why not ovp protection ?
HW MSM8917 PM8937 PMI8940 Question : Recently, I connect usb cable with 10V to the phone. Why does t ...
- 启动tomcat服务器自动执行一个方法
第一步:配置web.xml文件 添加如下代码 <servlet> <servlet-name>Timer</servlet-name> <servlet-cl ...