使用JDBC CallableStatements执行存储过程

Posted ting-3

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用JDBC CallableStatements执行存储过程相关的知识,希望对你有一定的参考价值。

使用JDBC CallableStatements执行存储过程

实验目的:掌握jdbc callableStatements 的执行过程。

实验内容:掌握jdbc 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字段。

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;

 

1
alter table t_employee add tyear int;

---恢复内容结束---

以上是关于使用JDBC CallableStatements执行存储过程的主要内容,如果未能解决你的问题,请参考以下文章

存储过程的实验

Apache DBUtils - 存储过程

使用 CallableStatement 调用 HSQLDB IDENTITY 函数以获取输出

使用jdbc连接mysql为啥报错?

JDBC01 利用JDBC连接数据库不使用数据库连接池

使用 JDBC 访问远程 MySQL 数据库时出现 com.mysql.jdbc.exceptions.jdbc4.CommunicationsException