今天针对JDBC中调用存储过程和存储函数进行了学习,学习内容如下:
1.JDBC中调用存储过程:
调用存储过程需要用到PreparedCall,专门用来处理调用存储过程和存储函数,迄今为止我学了三个Connection创建的陈述对象了,Statement,PreparedStatement和PreparedCall三个,前两个区别在于Statement是在executeQuery/ExecuteUpdate的时候进行SQL语句的执行,而PreparedStatement是在初始化的时候传入SQL语句,并在指定参数部位传入?占位,并在后续使用setObject/String/Int/Blob...进行参数设置,设置好之后使用execute执行SQL,Statement的执行流程是:解析->编译->优化->执行就是连续下来的一个过程,PreparedStatement的执行流程是:解析->编译->优化->缓存执行计划,然后在后续调用execute之后再执行,而PreparedCall的执行则是和PreparedStatement相同,只不过作用的是存储过程和存储函数罢了;
(1)调用无参的存储过程
javascript
create procedure noparam()
begin
select * from emp;
end;
javascript
public class TestNoParam {
public static void main(String[] args) throws SQLException {
//Statement
//PreparedStatement
Connection connection = DBUtil.getConnection();
String sql = "{call noparam()}";
CallableStatement callableStatement = connection.prepareCall(sql);
callableStatement.execute();//执行了存储过程
ResultSet resultSet = callableStatement.getResultSet();
//ResultSet resultSet = callableStatement.executeQuery();
while (resultSet.next()) {
System.out.print(resultSet.getString(1) + "\t");
System.out.print(resultSet.getString(2) + "\t");
System.out.print(resultSet.getString(3) + "\t");
System.out.print(resultSet.getString(4) + "\t");
System.out.print(resultSet.getString(5) + "\t");
System.out.println(resultSet.getString(6) + "\t");
}
DBUtil.close(callableStatement, connection);
}
}
(2)有入参的存储过程调用
sql
create procedure sell_pro(goodsId varchar(30),orderId varchar(32),n int)
begin
start transaction ;
insert into order_info values (default,goodsId,orderId,n);
update stock set num=num-n where goods_id=goodsId;
insert into records values (default,goodsId,n,now());
commit ;
end;
java
public class TestInParam {
public static void main(String[] args) throws SQLException {
Connection connection= DBUtil.getConnection();
String sql="{call sell_pro(?,?,?)}";
CallableStatement callableStatement = connection.prepareCall(sql);
callableStatement.setString(1,"1001");
callableStatement.setString(2,"20230102");
callableStatement.setInt(3,20);
callableStatement.execute();
DBUtil.close(callableStatement,connection);
}
}
(3)既有入参又有出参的存储过程调用:
sql
create procedure add_test( a int, b int,out c int )
begin
set c=a+b;
end;
java
public class TestOutParam {
public static void main(String[] args) throws SQLException {
Connection connection= DBUtil.getConnection();
String sql="{call add_test(?,?,?)}";
CallableStatement callableStatement = connection.prepareCall(sql);
callableStatement.setInt(1,10);
callableStatement.setInt(2,20);
//对应out参数的处理,标注参数类型
callableStatement.registerOutParameter(3, Types.INTEGER);
callableStatement.execute();
int anInt = callableStatement.getInt(3);
System.out.println(anInt);
DBUtil.close(callableStatement,connection);
}
}
(4)有特殊参数(INOUT)的调用
sql
create procedure mul(inout res int)
begin
set res=res*10;
end;
java
public class TestInOutParam {
public static void main(String[] args) throws SQLException {
Connection connection= DBUtil.getConnection();
String sql="{call mul(?)}";
CallableStatement callableStatement = connection.prepareCall(sql);
callableStatement.setInt(1,5);
//对应out参数的处理,标注参数类型
callableStatement.registerOutParameter(1, Types.INTEGER);
callableStatement.execute();
int anInt = callableStatement.getInt(1);
System.out.println(anInt);
DBUtil.close(callableStatement,connection);
}
}
(6)存储结果查询了多个结果集:
sql
create procedure selectMul(goodsId varchar(30))
begin
select * from order_info where goods_id = goodsId;
select * from stock where goods_id = goodsId;
select * from records where goods_id = goodsId;
end;
java
package demo;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
/**
* @author djw
*/
public class Test5 {
public static void main(String[] args) throws Exception {
Connection conn = DBUtil.getConnection();
CallableStatement callableStatement = conn.prepareCall("{call selectMul(?)}");
callableStatement.setString(1, "1001");
callableStatement.execute();
ResultSet rs = callableStatement.getResultSet();
while(rs.next()) {
for(int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
System.out.print(rs.getString(i) + "\t");
}
}
System.out.println("---------------------");
while (callableStatement.getMoreResults()) {
ResultSet resultSet = callableStatement.getResultSet();
while(resultSet.next()) {
for(int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) {
System.out.print(resultSet.getString(i) + "\t");
}
}
System.out.println();
System.out.println("--------------------");
}
DBUtil.close(conn, callableStatement);
}
}
这里可以使用元数据getMetaData来获取有多少行的统计值,以便于进行打印
2.再创建Statement/PreparedStatement/PreparedCall的时候可以传入参数以设置结果集的可滚动性,可更新性等特点:

3.调用函数:
java
public class TestFunction {
public static void main(String[] args) throws SQLException {
Connection connection= DBUtil.getConnection();
//调用自定义函数
CallableStatement callableStatement =
connection.prepareCall("{?=call getHiredate(?)}");
callableStatement.registerOutParameter(1, Types.DATE);
callableStatement.setString(2,"白居易");
callableStatement.execute();
System.out.println(callableStatement.getDate(1));
DBUtil.close(callableStatement,connection);
}
}
方式与有out参数的存储过程相似,只不过语法有所改变;