CallableStatement
主要是调用数据库中的存储过程,CallableStatement
也是Statement
的子接口。在使用CallableStatement时可以接收过程的返回值,此接口的常用方法如下表所示。
序号 | 方法 | 描述 |
---|---|---|
1 | int getInt(int parameterIndex) | 根据编号取出过程的int类型返回值 |
2 | float getFloat(int parameterIndex) | 根据编号取出纯纯过程的float类型返回值 |
3 | void setInt(String parameterName, int x) | 将指定的参数名称设置为给定的Java int值。 |
4 | void setFloat(String parameterName, float x) | 将指定的参数名称设置为给定的Java float值。 |
5 | void registerOutParameter(int parameterIndex, int sqlType) | 设置返回值的类型,需要使用Types类 |
在JDBC中,如果要设置过程的返回值类型,可以使用Types
完成。在Types
中定义了很过常量,如果现在返回类型为int
,则可以使用Types.INTEGER
.
下面是JDBC操作存储过程的例子,这里先在cmd命令行进入mysql
mysql -uroot -p
然后输入密码:root,进入mysql.
选择usersinfo数据库:
use usersinfo;
然后,开始创建一个存储过程myproc
:
delimiter #
drop procedure myproc #
create procedure myproc(in p1 int,inout p2 int,out p3 int)
begin
select p1,p2,p3;
set p1=10;
set p2=20;
set p3=30;
end
#
delimiter ;
运行效果:
在myproc的存储过程中,定义了三个变量,分别使用in,inout,out 三种类型声明,这三种类型的声明含义如下
in类型的,只用于将值传递到存储过程中,不能向外传出数据,也就是调用存储过程时x1可以赋值给p1。但是在存储过程运行中,修改p1的值对x1不会有任何影响。
inout类型,即可将值传到存储过程中,又可以从存储过程中向外传出数据,也就是说调用存储过程时,x2可以赋值给p2。在存储过程运行中修改p2,x2也会跟着改变。
out类型,只用于存储过程向外传递数据,不能用于传入数据,也就是说调用存储过程时,当x3的值不能传递给p3。在存储过程运行中修改了p3,x3的值也会跟着改变。
接着来设置三个变量x1
,x2
,x3
:
set @x1=70;
set @x2=80;
set @x3=90;
然后来调用存储过程:
call myproc(@x1,@x2,@x3);
运行结果:
分析:
在存储过程myproc
中的
第一条语句:select p1,p2,p3;
这条语句把传入到存储过程的参数输出一下,可以看到第一个参数p1=x1=70
,第二个参数p2=x2=80
,第三个参数p3=null;
可以看到x1传递给p1成功,x2传递给p2也成功,x3不能传值给p3
第二条语句:set p1=10;
这条语句把形式参数p1的值修改成10,但是p1是in类型的,所以p1的修改不影响x1,x1的值还是原来的70.
第三条语句:set p2=20;
这条语句把形式参数p2的值修改成20,因为p2是inout类型的,所以修改了p2,x2的值也会跟着改变,不再是原来的值,而是变成新的值20.
第四条语句:set p3=30;
这条语句把形式参数p3的值改成30,因为p3的值是out类型的,所以,修改了p3的值为30,x3也会变成30;
下面就来输出x1,x2,x3三个变量来验证上面说的对不对:
select @x1,@x2,@x3;
运行结果:
可以看到x1=70
不变,而x2=p2=20,x3=p3=30
。
从上面的结果可以发现,in操作只是将值传递进去,而本身不会被过程修改。而inout操作,即可以传递值,也可以被存储过程修改。out操作不能传递值,但可以被存储过程修改。
实例:使用jdbc调用myproc存储过程
package my.proc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.CallableStatement;
import java.sql.Types;
public class ProcDemo
{
// 定义MySQL的数据库驱动程序
public static final String driver = "com.mysql.jdbc.Driver";
// 定义MySQL数据库的连接地址
public static final String url = "jdbc:mysql://localhost:3306/usersinfo";
// MySQL数据库的连接用户名
public static final String user = "root";
// MySQL数据库的连接密码
public static final String password = "root";
public static void main(String args[]) throws Exception
{
// 数据库连接
Connection conn = null;
// 数据库存储过程操作
CallableStatement cstmt = null;
//调用存储过程的SQL语句
String sql = "{call myproc(?,?,?)}";
// 加载驱动程序
Class.forName(driver);
//建立数据库连接
conn = DriverManager.getConnection(url, user, password);
//实例化数据库存储过程操作
cstmt = conn.prepareCall(sql);
//设置设置第一个输入参数
cstmt.setInt(1, 70);
//设置第二个输入参数
cstmt.setInt(2, 80);
cstmt.setInt(3, 90);
//不能给输入参数注册输出类型
//Exception in thread "main" java.sql.SQLException: Parameter number 1 is not an OUT parameter
// cstmt.registerOutParameter(1, Types.INTEGER);
//设置第一个输出参数的输出类型
cstmt.registerOutParameter(2, Types.INTEGER);
//设置第二个输出参数的输出类型
cstmt.registerOutParameter(3, Types.INTEGER);
//输出编译好的存储过程操作语句
String toString=cstmt.toString();
System.out.println("mysql>"+toString.substring(toString.lastIndexOf(":")+1).trim());
//执行存储过程调用
cstmt.execute(); // 执行过程
//不能获取in类型的输出
// System.out.println("in参数的返回值:" + cstmt.getInt(1));
System.out.println("inout参数的返回值:" + cstmt.getInt(2));
System.out.println("out参数的返回值:" + cstmt.getInt(3));
cstmt.close();
conn.close(); // 数据库关闭
}
}
运行结果:
mysql>CALL myproc(70,80,90)
inout参数的返回值:20
out参数的返回值:30
可以看到,和我们手动操作数据库一样,inout,out类型的参数在过程中被修改都会影响输出值。