CallableStatements
執行存儲過程CallableStatement的全部超級接口爲PreparedStatement、Statement、Wrapper。其中繼承自PreparedStatement接口。CallableStatement主要是調用數據庫中的存儲過程。在使用CallableStatement時能夠接收存儲過程的返回值。CallableStatement對象爲全部的DBMS提供了一種標準的形式去調用數據庫中已存在的存儲過程。對數據庫中存儲過程的調用是CallableStatement對象所含的內容。有兩種形式:1:形式帶結果參數;2:形式不帶結果參數。結果參數是一種輸出參數(存儲過程當中的輸出OUT參數),是存儲過程的返回值。兩種形式都有帶有數量可變的輸入、輸出、輸入和輸出的參數。用問號作佔位符。java
形式帶結果參數語法格式:{ ? = call 存儲過程名[(?, ?, ?, ...)]};mysql
形式不帶結果參數語法格式:{ call 存儲過程名[(?, ?, ?, ...)]};PS方括號裏面的內容無關緊要。sql
CallableStatement接口中經常使用的方法。數據庫
1:getInt(int parameterIndex)、getInt(String parameterName)、還有getString、getBigDecimal、getString、getDate、getURL等等都相似和PreparedStatement與Statement中的用法相似。app
2:registerOutParameter(int parameterIndex, int sqlType):按順序位置parameterIndex將OUT參數註冊爲JDBC類型sqlType。ide
3:wasNull():查詢最後一個讀取的OUT參數是否爲SQL Null。等等還有不少方法,感興趣的讀者能夠自行查閱JDK API文檔。測試
講解了那麼多,不如一個例子來的痛快。下面經過一個例子讓讀者更清楚的看到CallableStatement的用法。this
首先在原先的t_employee表中添加表示幹了多少年的tyear字段。spa
1 alter table t_employee add tyear int;
在數據庫中編寫存儲過程統計指定id的userName的人,輸出一下他一共賺了多少錢。code
JDBC代碼:
1 package com.panli.dbutil; 2 /** 3 * 鏈接數據庫 4 */ 5 import java.sql.CallableStatement; 6 import java.sql.Connection; 7 import java.sql.DriverManager; 8 import java.sql.PreparedStatement; 9 import java.sql.ResultSet; 10 import java.sql.SQLException; 11 import java.sql.Statement; 12 13 public class DbUtil { 14 //數據庫驅動名字 15 private static String jdbcName = "com.mysql.jdbc.Driver"; 16 //數據庫協議地址 17 private static String dbUrl = "jdbc:mysql://localhost:3306/db_user"; 18 //數據庫用戶名 19 private static String dbUser = "root"; 20 //數據庫密碼 21 private static String dbPassword = "123456"; 22 23 24 /** 25 * 獲取鏈接 26 * @return 27 * @throws Exception 28 */ 29 public static Connection getCon() throws Exception{ 30 Class.forName(jdbcName); 31 Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword); 32 return conn; 33 } 34 35 /** 36 * 關閉鏈接 37 * @param stmt 38 * @param conn 39 * @throws Exception 40 */ 41 public static void close(Statement stmt,Connection conn) throws Exception{ 42 if(stmt!=null){ 43 stmt.close(); 44 if(conn!=null){ 45 conn.close(); 46 } 47 } 48 } 49 50 /** 51 * 關閉鏈接 52 * @param cstmt 53 * @param conn 54 * @throws Exception 55 */ 56 public static void close(CallableStatement cstmt, Connection conn) throws Exception{ 57 if(cstmt!=null){ 58 cstmt.close(); 59 if(conn!=null){ 60 conn.close(); 61 } 62 } 63 } 64 65 66 /** 67 * 關閉鏈接 68 * @param pstmt 69 * @param conn 70 * @throws SQLException 71 */ 72 public static void close(PreparedStatement pstmt, Connection conn) throws SQLException{ 73 if(pstmt!=null){ 74 pstmt.close(); 75 if(conn!=null){ 76 conn.close(); 77 } 78 } 79 } 80 81 82 /** 83 * 重載關閉方法 84 * @param pstmt 85 * @param conn 86 * @throws Exception 87 */ 88 public void close(ResultSet rs,PreparedStatement pstmt, Connection conn) throws Exception{ 89 if(rs!=null){ 90 rs.close(); 91 if(pstmt!=null){ 92 pstmt.close(); 93 if(conn!=null){ 94 conn.close(); 95 } 96 97 } 98 } 99 100 } 101 }
1 package com.panli.model; 2 3 import java.io.File; 4 5 /** 6 * model包下的cemployee類,對每一個字段進行建模 7 * @author Peter 8 * 9 */ 10 public class CEmployee { 11 private int id; 12 private String userName; 13 private double salary; 14 private String job; 15 private int jobTypeId; 16 private File context; 17 private File pic; 18 private double counts; 19 /** 20 * 默認的構造方法 21 */ 22 public CEmployee() { 23 super(); 24 // TODO Auto-generated constructor stub 25 } 26 27 /** 28 * 帶一個參數的構造方法 29 * @param id 30 */ 31 public CEmployee(int id) { 32 super(); 33 this.id = id; 34 } 35 36 /** 37 * 兩個參數的構造方法 38 * @param counts 39 * @param userNames 40 */ 41 public CEmployee(double counts, String userName) { 42 // TODO Auto-generated constructor stub 43 this.counts = counts; 44 this.userName = userName; 45 } 46 47 /** 48 * 重寫toString()方法 49 */ 50 @Override 51 public String toString(){ 52 return userName+"一共賺了"+counts+"錢"; 53 } 54 public int getId() { 55 return id; 56 } 57 public void setId(int id) { 58 this.id = id; 59 } 60 public String getUserName() { 61 return userName; 62 } 63 public void setUserName(String userName) { 64 this.userName = userName; 65 } 66 public double getSalary() { 67 return salary; 68 } 69 public void setSalary(double salary) { 70 this.salary = salary; 71 } 72 public String getJob() { 73 return job; 74 } 75 public void setJob(String job) { 76 this.job = job; 77 } 78 public int getJobTypeId() { 79 return jobTypeId; 80 } 81 public void setJobTypeId(int jobTypeId) { 82 this.jobTypeId = jobTypeId; 83 } 84 85 public File getContext() { 86 return context; 87 } 88 89 public void setContext(File context) { 90 this.context = context; 91 } 92 93 public File getPic() { 94 return pic; 95 } 96 97 public void setPic(File pic) { 98 this.pic = pic; 99 } 100 101 public double getCounts() { 102 return counts; 103 } 104 105 public void setCounts(double counts) { 106 this.counts = counts; 107 } 108 109 }
1 package com.panli.dao; 2 3 import java.sql.CallableStatement; 4 import java.sql.Connection; 5 import java.sql.Types; 6 import java.util.ArrayList; 7 import java.util.List; 8 9 import com.panli.dbutil.DbUtil; 10 import com.panli.model.CEmployee; 11 12 public class CountsEmployeeDao { 13 private static DbUtil dbUtil = new DbUtil(); 14 /** 15 * 調用存儲過程獲得指定ID用戶的一共賺了多少錢 16 * @param employee 17 * @return 18 * @throws Exception 19 */ 20 public static List getCountsById(CEmployee cemployee)throws Exception{ 21 List list = new ArrayList(); 22 Connection conn = dbUtil.getCon(); 23 String sql = "{call pro_getCountById(?, ?, ?)}"; 24 CallableStatement cstmt = conn.prepareCall(sql); 25 cstmt.setInt(1, cemployee.getId()); 26 cstmt.registerOutParameter(2, Types.DOUBLE); 27 cstmt.registerOutParameter(3, Types.VARCHAR); 28 cstmt.execute(); 29 double counts = cstmt.getDouble("counts"); 30 String userNames = cstmt.getString("userNames"); 31 CEmployee emp = new CEmployee(counts, userNames); 32 list.add(emp); 33 dbUtil.close(cstmt, conn); 34 return list; 35 } 36 /** 37 * 作測試的主方法 38 * @param args 39 */ 40 public static void main(String[] args)throws Exception { 41 42 CEmployee cemployee = new CEmployee(1); 43 List list = getCountsById(cemployee); 44 for(CEmployee cemp: list){ 45 System.out.println(cemp); 46 } 47 } 48 }
建立的存儲過程爲:
1 delimiter && 2 create procedure pro_getCountById(in tid int, out counts double, out userNames varchar(20)) 3 begin 4 select salary*tyear into counts from t_employee where id = tid; 5 select userName into userNames from t_employee where id = tid; 6 end 7 && 8 9 測試: 10 call pro_getCountById(1, @counts, @userNames); 11 select @counts, @userNames;