首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

JDBC 調用 MySQL 存儲過程完整實戰教程

     編輯:MySQL 資料庫相關知識

本文通過一個具體的「兩數相乘」示例,詳細演示如何在 MySQL 中創建帶輸出參數的存儲過程,並使用 JDBC 的 CallableStatement 進行調用、參數綁定與結果獲取。

一、 數據庫端:創建存儲過程

登入 MySQL 客戶端,執行以下腳本:

DELIMITER //

DROP PROCEDURE IF EXISTS add_pro //

CREATE PROCEDURE add_pro(
    IN a INT,
    IN b INT,
    OUT sum INT
)
BEGIN
    SET sum = a * b;
END //

DELIMITER ;

關鍵點解析:

  • DELIMITER //:臨時修改語句結束符,避免過程體內的 ; 提前終止創建語句。
  • IN:輸入參數;OUT:輸出參數;亦可用 INOUT 表示雙向參數。
  • 過程體內直接賦值給 OUT 參數即可返回結果。

二、 Java 端:JDBC 調用代碼

package com.example.demo;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Types;

public class CallableStatementDemo {

    private static final String URL = "jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC";
    private static final String USER = "root";
    private static final String PASSWORD = "123456";
    private static final String DRIVER = "com.mysql.cj.jdbc.Driver";  // MySQL 8.0+ 驅動類

    public static void main(String[] args) {
        Connection conn = null;
        CallableStatement cstmt = null;

        try {
            // 1. 加載驅動(JDBC 4.0+ 可省略,保留兼容性)
            Class.forName(DRIVER);

            // 2. 建立連接
            conn = DriverManager.getConnection(URL, USER, PASSWORD);

            // 3. 準備調用語法:{CALL 過程名(?, ?, ?)} 佔位符對應 IN/IN/OUT
            String sql = "{CALL add_pro(?, ?, ?)}";
            cstmt = conn.prepareCall(sql);

            // 4. 綁定輸入參數(索引從 1 開始)
            cstmt.setInt(1, 122);  // a
            cstmt.setInt(2, 2);    // b

            // 5. 註冊輸出參數類型(關鍵步驟!)
            cstmt.registerOutParameter(3, Types.INTEGER);

            // 6. 執行存儲過程
            cstmt.execute();

            // 7. 獲取輸出參數值
            int result = cstmt.getInt(3);
            System.out.println("計算結果 (122 * 2) = " + result);  // 輸出 244

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 8. 釋放資源(逆序關閉)
            try { if (cstmt != null) cstmt.close(); } catch (Exception ignore) {}
            try { if (conn != null) conn.close(); } catch (Exception ignore) {}
        }
    }
}

三、 核心 API 誦解

方法說明
Connection.prepareCall(String sql)創建 CallableStatement 對象,預編譯調用語句
setXxx(int idx, Xxx val)綁定 IN/INOUT 參數,idx 為佔位符位置(1-based)
registerOutParameter(int idx, int sqlType)註冊 OUT/INOUT 參數的 JDBC 類型(java.sql.Types)
execute()執行存儲過程,返回 boolean(是否有 ResultSet)
getXxx(int idx)獲取 OUT/INOUT 參數值

四、 進階場景與最佳實踐

1. 處理結果集(SELECT 返回)

若存儲過程包含 SELECT 語句,執行後可獲取 ResultSet:

boolean hasResults = cstmt.execute();
if (hasResults) {
    try (ResultSet rs = cstmt.getResultSet()) {
        while (rs.next()) { /* 處理行數據 */ }
    }
    // 如有多個結果集,需循環 cstmt.getMoreResults() 獲取
}

2. 使用具名參數(MySQL 8.0.16+ / MariaDB 10.2+)

cstmt.setInt("a", 122);  // 按參數名綁定,無需記住順序
cstmt.registerOutParameter("sum", Types.INTEGER);
int result = cstmt.getInt("sum");

3. 連接池與事務管理

  • 生產環境務必使用連接池,推薦 HikariCP。
  • 存儲過程若涉及多步寫入,建議在過程內部控制事務(START TRANSACTION; COMMIT/ROLLBACK;),或在 Java 端設置 conn.setAutoCommit(false) 統一控制。

4. 常見坑點排查

  • 參數順序錯誤:registerOutParameter 的索引必須與 {CALL ... (?, ?, ?)} 中佔位符位置一致。
  • 類型不匹配:數據庫 BIGINT 對應 Types.BIGINT/getLong(),DECIMAL 對應 Types.DECIMAL/getBigDecimal()。
  • 驅動版本:MySQL 8.0 必須用 com.mysql.cj.jdbc.Driver,舊驅動 com.mysql.jdbc.Driver 已棄用。

五、 總結

JDBC 調用 MySQL 存儲過程的核心流程是:定義 SQL 調用語法 → 準備 CallableStatement → 綁定輸入參數 → 註冊輸出參數類型 → 執行 → 讀取輸出值 → 關閉資源。掌握 registerOutParameter 類型映射與資源釋放順序,即可穩健應對各類存儲過程調用場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved