在JDBC API中提供了調用存儲過程的方法,通過CallableStatement對象進行操作。CallableStatement對象位於java.sql包中,它繼承於Statement對象,主要用於執行數據庫中定義的存儲過程,其調用方法如下:
{call <procedure-name>[(<arg1>,<arg2>,...)]}
其中,arg1、arg2為存儲過程中的參數,如果存儲過程中需要傳遞參數,可以對其進行賦值操作。
技巧:存儲過程是一個SQL語句和可選控制流語句的預編譯集合。編譯完成后存放在數據庫中,這樣就省去了執行SQL語句時對SQL語句進行編譯所花費的時間。在執行存儲過程時只需要將參數傳遞到數據庫中,而不需要將整條SQL語句都提交給數據庫,從而減少了網絡傳輸的流量,從另一方面提高了程序的運行速度。
例1.1 創建查詢所有圖書信息的存儲過程,通過JDBC API對其調用獲取所有圖書信息,並將其輸出到JSP頁面中。
(1)在數據庫test中創建名稱為findAllBook的存儲過程,用於查詢所有圖書信息。關鍵代碼如下:
BEGIN SELECT* FROM books ORDER BY id DESC; END
各種數據庫創建存儲過程的方法並非一致,本實例使用的是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; } }
(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; }
然后編寫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; }
由於存儲過程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>
實例運行后,進入到index1.jsp頁面,程序將執行數據庫中定義的存儲過程findAllBook查詢圖書信息,其運行結果如下圖所示: