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
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
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();
}
}
}
}
}
|
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
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;
}
}
|
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
47
48
|
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);
}
}
}
|
建立的存儲過程爲:
1
2
3
4
5
6
7
8
9
10
11
|
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
;
|
CallableStatements
執行存儲過程CallableStatement的全部超級接口爲PreparedStatement、Statement、Wrapper。其中繼承自PreparedStatement接口。CallableStatement主要是調用數據庫中的存儲過程。在使用CallableStatement時能夠接收存儲過程的返回值。CallableStatement對象爲全部的DBMS提供了一種標準的形式去調用數據庫中已存在的存儲過程。對數據庫中存儲過程的調用是CallableStatement對象所含的內容。有兩種形式:1:形式帶結果參數;2:形式不帶結果參數。結果參數是一種輸出參數(存儲過程當中的輸出OUT參數),是存儲過程的返回值。兩種形式都有帶有數量可變的輸入、輸出、輸入和輸出的參數。用問號作佔位符。
形式帶結果參數語法格式:{ ? = call 存儲過程名[(?, ?, ?, ...)]};
形式不帶結果參數語法格式:{ call 存儲過程名[(?, ?, ?, ...)]};PS方括號裏面的內容無關緊要。
CallableStatement接口中經常使用的方法。
1:getInt(int parameterIndex)、getInt(String parameterName)、還有getString、getBigDecimal、getString、getDate、getURL等等都相似和PreparedStatement與Statement中的用法相似。
2:registerOutParameter(int parameterIndex, int sqlType):按順序位置parameterIndex將OUT參數註冊爲JDBC類型sqlType。
3:wasNull():查詢最後一個讀取的OUT參數是否爲SQL Null。等等還有不少方法,感興趣的讀者能夠自行查閱JDK API文檔。
講解了那麼多,不如一個例子來的痛快。下面經過一個例子讓讀者更清楚的看到CallableStatement的用法。
首先在原先的t_employee表中添加表示幹了多少年的tyear字段。
1
|
alter table t_employee add tyear
int
;
|
在數據庫中編寫存儲過程統計指定id的userName的人,輸出一下他一共賺了多少錢。
JDBC代碼:
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
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();
}
}
}
}
}
|
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
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;
}
}
|
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
47
48
|
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);
}
}
}
|
建立的存儲過程爲:
1
2
3
4
5
6
7
8
9
10
11
|
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
;
|