在JDBC API中提供了调用存储过程的方法,通过CallableStatement对象进行操作。CallableStatement对象位于Java.sql包中,它继承于Statement对象,主要用于执行数据库中定义的存储过程,其调用方法如下:
{call <procedure-name>[(<arg1>,<arg2>,...)]}
- 1
- 1
其中,arg1、arg2为存储过程中的参数,如果存储过程中需要传递参数,可以对其进行赋值操作。
技巧:存储过程是一个SQL语句和可选控制流语句的预编译集合。编译完成后存放在数据库中,这样就省去了执行SQL语句时对SQL语句进行编译所花费的时间。在执行存储过程时只需要将参数传递到数据库中,而不需要将整条SQL语句都提交给数据库,从而减少了网络传输的流量,从另一方面提高了程序的运行速度。
例1.1 创建查询所有图书信息的存储过程,通过JDBC API对其调用获取所有图书信息,并将其输出到JSP页面中。
(1)在数据库test中创建名称为findAllBook的存储过程,用于查询所有图书信息。关键代码如下:
BEGIN
SELECT* FROM books ORDER BY id DESC;
END
- 1
- 2
- 3
- 1
- 2
- 3
各种数据库创建存储过程的方法并非一致,本实例使用的是MySQL数据库,如果使用其他数据库创建存储过程请参阅数据库提供的帮助文档。
(2) 创建名称为Book的类,该类用于封装图书信息的JavaBean对象。关键代码如下:
复制代码
package com.cn.gao;
public class Book {
private int id;
private String name;
private double price;
private int bookCount;
private String author;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getBookCount() {
return bookCount;
}
public void setBookCount(int bookCount) {
this.bookCount = bookCount;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
(3)创建名称为FindBook的类,用于执行查询图书信息的存储过程。首先在该类中编写getConnection()方法,获取数据库连接对象Connection,其关键代码如下:
复制代码
/**
* 获取数据库连接
* @return Connection 对象
*/
public Connection getConnection(){
Connection conn=null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/test";
String user = "root";
String password = "1234";
conn=DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
然后编写findAll()方法,调用数据库中定义的存储过程findAllBook,查询所有图书信息,并将查询到的图书的信息放置到List集合中。关键代码如下:
/**
* 通过存储过程查询数据
* @return List<Book>
*/
public List<Book> findAll(){
List<Book> list = new ArrayList<Book>();
Connection conn = getConnection();
try {
//调用存储过程
CallableStatement cs = conn.prepareCall("{call findAllBook()}");
ResultSet rs = cs.executeQuery(); //执行查询操作,并获取结果集
while(rs.next()){
Book book = new Book();
book.setId(rs.getInt("id"));
book.setName(rs.getString("name"));
book.setPrice(rs.getDouble("price"));
book.setBookCount(rs.getInt("bookCount"));
book.setAuthor(rs.getString("author"));
list.add(book);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
由于存储过程findAllBook中没有定义参数,所以实例中通过调用“{call findAllBook()}”来调用存储过程。
(4)创建程序中的主页index1.jsp,在该页面中实例化FindBook对象,并调用它的findAll()方法获取所有图书信息,将图书信息数据显示在页面中。关键代码如下:
<%@ page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030"%>
<%@ page import="java.util.*" %>
<%@ page import="com.cn.gao.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Insert title here</title>
</head>
<body>
<jsp:useBean id="findBook" class="com.cn.gao.FindBook"></jsp:useBean>
<table align="center" width="450" border="1">
<tr>
<td align="center" colspan="5">
<h2>所有图书信息</h2>
</td>
</tr>
<tr align="center">
<td><b>ID</b></td>
<td><b>图书名称</b></td>
<td><b>价格</b></td>
<td><b>数量</b></td>
<td><b>作者</b></td>
</tr>
<%
List<Book> list = findBook.findAll();
if(list==null||list.size()<1){
out.print("没有数据!");
}else{
for(Book book:list){
%>
<tr align="center">
<td><%=book.getId() %></td>
<td><%=book.getName() %></td>
<td><%=book.getPrice() %></td>
<td><%=book.getBookCount() %></td>
<td><%=book.getAuthor() %></td>
</tr>
<%
}
}
%>
</table>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
实例运行后,进入到index1.jsp页面,程序将执行数据库中定义的存储过程findAllBook查询图书信息,其运行结果如下图所示:
注意一下几点:
存储过程,相当于数据库中的函数或方法。现举例来说明使用JDBC调用存储过程。
编写存储过程(参看mysql文档)
delimiter $$
接收一个输入参数
create procedure demoSp(in inputParam varchar(255), inout inOutParam varchar(255))
begin 在传进来的字符串前加上zyxw---,然后将结果into到第二个参数
select concat('zyxw---', inputParam) into inOutParam;
end $$
delimiter ;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
得到CallableStatement,并调用存储过程
public class Demo5 {
// 调用存储过程
public static void main(String[] args) throws SQLException {
Connection conn = null;
CallableStatement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
// 得到CallableStatement,并调用存储过程
st = conn.prepareCall("call demoSp(?,?)");
// 设置参数,注册返回值,得到输出
st.setString(1, "叶磊磊");
st.registerOutParameter(2, Types.VARCHAR); // 告诉MySQL驱动输出的是什么类型,即数据库的类型,Types类中有所有数据库的常见类型
st.execute();
System.out.println(st.getString(2));
} finally {
JdbcUtils.release(conn, st, rs);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
学了存储过程,将来对数据进行处理就有2种选择了。
在数据库里面写存储过程,对数据进行处理,然后在java程序里面直接调用存储过程,获取到处理完后的数据,直接显示即可。不在数据库里面写存储过程,通过JDBC获取数据库中的数据,获取到了之后拿到程序里面写方法来处理,处理完后再显示。
什么情况下我们需要在数据库里面写存储过程来处理数据呢?
银行的数据处理一般用存储过程来实现。银行那些业务都是写好存储过程后给你,你去调用存储过程即可。在金融证劵领域用到的特别多,金融证劵领域的开发是不会用hibernate框架,因为表结构不会对开发人员公开。