stored procedure connector/j 8.0 Developer guide7.3存儲過程的實驗。實驗報告形式寫博客java
CallableStatements
執行存儲過程CallableStatement的全部超級接口爲PreparedStatement、Statement、Wrapper。其中繼承自PreparedStatement接口。CallableStatement主要是調用數據庫中的存儲過程。在使用CallableStatement時能夠接收存儲過程的返回值。CallableStatement對象爲全部的DBMS提供了一種標準的形式去調用數據庫中已存在的存儲過程。對數據庫中存儲過程的調用是CallableStatement對象所含的內容。有兩種形式:1:形式帶結果參數;2:形式不帶結果參數。結果參數是一種輸出參數(存儲過程當中的輸出OUT參數),是存儲過程的返回值。兩種形式都有帶有數量可變的輸入、輸出、輸入和輸出的參數。用問號作佔位符。mysql
形式帶結果參數語法格式:{ ? = call 存儲過程名[(?, ?, ?, ...)]};sql
形式不帶結果參數語法格式:{ call 存儲過程名[(?, ?, ?, ...)]};PS方括號裏面的內容無關緊要。數據庫
CallableStatement接口中經常使用的方法。app
1:getInt(int parameterIndex)、getInt(String parameterName)、還有getString、getBigDecimal、getString、getDate、getURL等等都相似和PreparedStatement與Statement中的用法相似。ide
2:registerOutParameter(int parameterIndex, int sqlType):按順序位置parameterIndex將OUT參數註冊爲JDBC類型sqlType。測試
3:wasNull():查詢最後一個讀取的OUT參數是否爲SQL Null。等等還有不少方法,感興趣的讀者能夠自行查閱JDK API文檔。ui
講解了那麼多,不如一個例子來的痛快。下面經過一個例子讓讀者更清楚的看到CallableStatement的用法。this
首先在原先的t_employee表中添加表示幹了多少年的tyear字段。spa
alter table t_employee add tyear int;
在數據庫中編寫存儲過程統計指定id的userName的人,輸出一下他一共賺了多少錢。
JDBC代碼:
package com.panli.dbutil; /** * 鏈接數據庫 */ import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DbUtil { //數據庫驅動名字 private static String jdbcName = "com.mysql.jdbc.Driver"; //數據庫協議地址 private static String dbUrl = "jdbc:mysql://localhost:3306/db_user"; //數據庫用戶名 private static String dbUser = "root"; //數據庫密碼 private static String dbPassword = "123456"; /** * 獲取鏈接 * @return * @throws Exception */ public static Connection getCon() throws Exception{ Class.forName(jdbcName); Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword); return conn; } /** * 關閉鏈接 * @param stmt * @param conn * @throws Exception */ public static void close(Statement stmt,Connection conn) throws Exception{ if(stmt!=null){ stmt.close(); if(conn!=null){ conn.close(); } } } /** * 關閉鏈接 * @param cstmt * @param conn * @throws Exception */ public static void close(CallableStatement cstmt, Connection conn) throws Exception{ if(cstmt!=null){ cstmt.close(); if(conn!=null){ conn.close(); } } } /** * 關閉鏈接 * @param pstmt * @param conn * @throws SQLException */ public static void close(PreparedStatement pstmt, Connection conn) throws SQLException{ if(pstmt!=null){ pstmt.close(); if(conn!=null){ conn.close(); } } } /** * 重載關閉方法 * @param pstmt * @param conn * @throws Exception */ public void close(ResultSet rs,PreparedStatement pstmt, Connection conn) throws Exception{ if(rs!=null){ rs.close(); if(pstmt!=null){ pstmt.close(); if(conn!=null){ conn.close(); } } } } }
package com.panli.model; import java.io.File; /** * model包下的cemployee類,對每一個字段進行建模 * @author Peter * */ public class CEmployee { private int id; private String userName; private double salary; private String job; private int jobTypeId; private File context; private File pic; private double counts; /** * 默認的構造方法 */ public CEmployee() { super(); // TODO Auto-generated constructor stub } /** * 帶一個參數的構造方法 * @param id */ public CEmployee(int id) { super(); this.id = id; } /** * 兩個參數的構造方法 * @param counts * @param userNames */ public CEmployee(double counts, String userName) { // TODO Auto-generated constructor stub this.counts = counts; this.userName = userName; } /** * 重寫toString()方法 */ @Override public String toString(){ return userName+"一共賺了"+counts+"錢"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public String getJob() { return job; } public void setJob(String job) { this.job = job; } public int getJobTypeId() { return jobTypeId; } public void setJobTypeId(int jobTypeId) { this.jobTypeId = jobTypeId; } public File getContext() { return context; } public void setContext(File context) { this.context = context; } public File getPic() { return pic; } public void setPic(File pic) { this.pic = pic; } public double getCounts() { return counts; } public void setCounts(double counts) { this.counts = counts; } }
package com.panli.dao; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.Types; import java.util.ArrayList; import java.util.List; import com.panli.dbutil.DbUtil; import com.panli.model.CEmployee; public class CountsEmployeeDao { private static DbUtil dbUtil = new DbUtil(); /** * 調用存儲過程獲得指定ID用戶的一共賺了多少錢 * @param employee * @return * @throws Exception */ public static List getCountsById(CEmployee cemployee)throws Exception{ List list = new ArrayList(); Connection conn = dbUtil.getCon(); String sql = "{call pro_getCountById(?, ?, ?)}"; CallableStatement cstmt = conn.prepareCall(sql); cstmt.setInt(1, cemployee.getId()); cstmt.registerOutParameter(2, Types.DOUBLE); cstmt.registerOutParameter(3, Types.VARCHAR); cstmt.execute(); double counts = cstmt.getDouble("counts"); String userNames = cstmt.getString("userNames"); CEmployee emp = new CEmployee(counts, userNames); list.add(emp); dbUtil.close(cstmt, conn); return list; } /** * 作測試的主方法 * @param args */ public static void main(String[] args)throws Exception { CEmployee cemployee = new CEmployee(1); List list = getCountsById(cemployee); for(CEmployee cemp: list){ System.out.println(cemp); } } }
建立的存儲過程爲:
delimiter && create procedure pro_getCountById(in tid int, out counts double, out userNames varchar(20)) begin select salary*tyear into counts from t_employee where id = tid; select userName into userNames from t_employee where id = tid; end && 測試: call pro_getCountById(1, @counts, @userNames); select @counts, @userNames;