JDBC对MySQL数据库存储过程的调用
1、什么是存储过程
存储过程(英文:Stored Procedure)是在大型数据库系统中,为了完成特定功能而编写的一组的SQL语句集。存储过程经编译存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
2、与一般SQL语句相比,使用存储过程有哪些优点,有哪些缺点
优点:
1)、减少了脚本的执行环节,缩短了获取数据的时间。存储过程只在创建的时进行编译,在调用使用的时候直接执行,不需再次编译;而一般SQL语句每次执行前都需要编译一次,故效率没有存储过程高;
2)、减少网络传输量,提高了传输速度。存储过程编译后存储在数据库服务器上,使用的时候只需要指定存储过程的名字并给出参数(如果该存储过程带有参数)就可以了;而一般SQL语句需要将所执行语句字符串传输到数据库服务器端,相比于存储过程而言向数据库服务端传送的字符串长度比较大;
3)、安全性比较高。为存储过程参数赋值只能使用问号传参的形式(这一点可以通过下面JDBC对mysql数据库存储过程的调用例子体现出来),这样可以防止SQL注入式攻击;一般SQL语句也可以做到防止SQL注入式攻击,但是并不是必须的。可以将Grant、Deny以及Revoke权限应用于存储过程,即言可以设定只有某些用户才具有对指定存储过程的使用权;
缺点:
1)、如果在一个程序系统中大量的使用存储过程,当程序交付使用的时候随着客户需求的增加会导致数据结构的变化,接着就是存储过程的修改,这样系统维护就会越来越难并且代价也会越来越大。
3、怎样创建存储过程及创建存储过程需要注意的地方
存储过程的创建格式为:
create procedure 存储过程名([[IN |OUT |INOUT ] 参数名 数据类形...])
begin
存储过程体
end
创建存储过程的具体例子见下面JDBC对MySQL数据库存储过程的调用例子;
需要注意的地方:见下面JDBC对MySQL数据库存储过程的调用例子内创建存储过程语句中的注释;
二、JDBC对MySQL数据库存储过程的调用:
为了更加直观的介绍JDBC如何实现对MySQL数据库存储过程的调用,这里直接以例子的形式展示。
1、没有任何输入和输出参数的存储过程
1 drop PROCEDURE if EXISTS jdbcprocnoinandout; 2 create PROCEDURE jdbcprocnoinandout() 3 BEGIN 4 select * from test.test; 5 end;
下面是Java代码:
1 Connection connectionNoInAndOut = MyConnection.getConnection(); 2 String jdbcprocNoInAndOut = "{call jdbcprocnoinandout()}"; 3 CallableStatement csNoInAndOut = connectionNoInAndOut.prepareCall(jdbcprocNoInAndOut); 4 csNoInAndOut.execute(); 5 ResultSet rsNoInAndOut = csNoInAndOut.getResultSet(); 6 while (rsNoInAndOut.next()) { 7 System.out.println("jdbcprocnoinandout:"+rsNoInAndOut.getString("id")+"--------"+rsNoInAndOut.getString("value1")); 8 } 9 MyConnection.closeConnection(connectionNoInAndOut, csNoInAndOut, rsNoInAndOut);
2、只有两个输入参数的存储过程
1 drop PROCEDURE if EXISTS jdbcprocallin; 2 create PROCEDURE jdbcprocallin(id int, value1 VARCHAR(20)) 3 BEGIN 4 insert into test.test values(id,value1); 5 select * from test.test; 6 end;
Java代码:
1 Connection connectionAllIn = MyConnection.getConnection(); 2 String jdbcprocAllIn = "{call jdbcprocallin(?,?)}"; 3 CallableStatement csAllIn = connectionAllIn.prepareCall(jdbcprocAllIn); 4 csAllIn.setInt(1, 1); 5 csAllIn.setString(2, "asdf"); 6 csAllIn.execute(); 7 ResultSet rsAllIn = csAllIn.getResultSet(); 8 while (rsAllIn.next()) { 9 System.out.println("jdbcprocallin:"+rsAllIn.getString("id")+"--------"+rsAllIn.getString("value1")); 10 } 11 MyConnection.closeConnection(connectionAllIn, csAllIn, rsAllIn);
3、一个输入参数一个输出参数的存储过程
1 drop PROCEDURE if EXISTS jdbcprocinandout; 2 create PROCEDURE jdbcprocinandout(in id VARCHAR(20), out value1 VARCHAR(20)) 3 BEGIN 4 set value1 = CONCAT('我是:',id); 5 select value1; 6 end;
Java代码:
1 Connection connectionInAndOut = MyConnection.getConnection(); 2 String jdbcprocInAndOut = "{call jdbcprocinandout(?,?)}"; 3 CallableStatement csInAndOut = connectionInAndOut.prepareCall(jdbcprocInAndOut); 4 csInAndOut.setString(1, "123123"); 5 csInAndOut.registerOutParameter(2, Types.VARCHAR); 6 csInAndOut.execute(); 7 ResultSet rsInAndOut = csInAndOut.getResultSet(); 8 while (rsInAndOut.next()) { 9 System.out.println("jdbcprocinandout:"+csInAndOut.getString("value1")); 10 } 11 MyConnection.closeConnection(connectionInAndOut, csInAndOut, rsInAndOut);
4、两个输出参数的存储过程
1 drop PROCEDURE if EXISTS jdbcprocallout; 2 create PROCEDURE jdbcprocallout(out outid VARCHAR(20), out outvalue1 VARCHAR(20)) 3 BEGIN 4 select * into outid,outvalue1 from test.test limit 1; 5 select outid,outvalue1 ; 6 end;
Java代码:
1 Connection connectionAllOut = MyConnection.getConnection(); 2 String jdbcprocAllOut = "{call jdbcprocallout(?,?)}"; 3 CallableStatement csAllOut = connectionAllOut.prepareCall(jdbcprocAllOut); 4 csAllOut.registerOutParameter(1, Types.VARCHAR); 5 csAllOut.registerOutParameter(2, Types.VARCHAR); 6 csAllOut.execute(); 7 ResultSet rsAllOut = csAllOut.getResultSet(); 8 while (rsAllOut.next()) { 9 System.out.println("jdbcprocallout:"+csAllOut.getString("outid")+"--------"+csAllOut.getString("outvalue1")); 10 } 11 MyConnection.closeConnection(connectionAllOut, csAllOut, rsAllOut);
数据库中调用带有输出参数的存储过程写法,例如刚才两个带有输出参数的
1 call jdbcprocinandout('lily',@value1); 2 call jdbcprocallout(@vid,@vvalue);
-- 输出参数前面必须带“@”符号,变量名可以随便写一个合法变量都可以。
附上MyConnection类
1 package net.lily.test; 2 3 import java.sql.*; 4 5 public class MyConnection { 6 7 public static Connection getConnection() { 8 Connection connection = null; 9 String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useOldAliasMetadataBehavior=true"; 10 String user = "root"; 11 String pwd = "123456"; 12 String driverName = "com.mysql.jdbc.Driver"; 13 try { 14 Class.forName(driverName); 15 connection = DriverManager.getConnection(url, user, pwd); 16 } catch (ClassNotFoundException e) { 17 e.printStackTrace(); 18 } catch (SQLException e) { 19 e.printStackTrace(); 20 } 21 return connection; 22 } 23 24 public static void closeConnection(Connection con, PreparedStatement ps, ResultSet rs) { 25 if (rs != null) { 26 try { 27 rs.close(); 28 } catch (SQLException e) { 29 e.printStackTrace(); 30 } 31 } 32 if (ps != null) { 33 try { 34 ps.close(); 35 } catch (SQLException e) { 36 e.printStackTrace(); 37 } 38 } 39 if (con != null) { 40 try { 41 con.close(); 42 } catch (SQLException e) { 43 e.printStackTrace(); 44 } 45 } 46 } 47 }