首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

JDBC 預存程序與事務控制實戰指南

     編輯:DB2 教學

JDBC 預存程序與事務控制實戰指南

一、MySQL 預存程序基礎

1. 常用指令

-- 查看現有預存程序
SHOW PROCEDURE STATUS \G

-- 建立預存程序 (修改結束符避免衝突)
DELIMITER $
CREATE PROCEDURE proc_name(參數列表)
BEGIN
    -- 程序體:可使用 IF/ELSE、WHILE、變數宣告等
    DECLARE 變數名 型別;
    SET 變數名 = 值;
    SELECT 變數名;  -- 輸出/除錯
    INSERT ...;     -- DML 操作
END$
DELIMITER ;

-- 呼叫預存程序
CALL proc_name();
CALL proc_name(參數);

-- 刪除預存程序
DROP PROCEDURE proc_name;

2. 範例:計算 1+2+...+n 並寫入表

DELIMITER $
CREATE PROCEDURE calc_sum(IN p_name CHAR(10), IN p_n SMALLINT)
BEGIN
    DECLARE i INT DEFAULT 1;
    DECLARE s INT DEFAULT 0;
    WHILE i <= p_n DO
        SET s = s + i;
        SET i = i + 1;
    END WHILE;
    INSERT INTO test(name, age, score) VALUES (p_name, 0, s);
END$
DELIMITER ;

二、JDBC 呼叫預存程序:CallableStatement

方法說明
conn.prepareCall("{call proc(?,?)}")建立 CallableStatement,大括號為 JDBC Escape 語法
cs.setString(1, "值")綁定 IN 參數 (索引從 1 起)
cs.registerOutParameter(2, Types.INTEGER)註冊 OUT 參數型別
cs.execute()執行預存程序
cs.getInt(2)取得 OUT 參數值

完整範例

package com.example.jdbc;
import java.sql.*;

public class JdbcCallableDemo {
    private static final String URL = "jdbc:mysql://localhost:3306/jdbc_test_db";
    private static final String USER = "root", PASS = "111111";

    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(URL, USER, PASS);
             CallableStatement cs = conn.prepareCall("{call calc_sum(?, ?)}")) {

            cs.setString(1, "proc_call");  // p_name
            cs.setInt(2, 100);             // p_n
            cs.execute();
            System.out.println("預存程序執行完成,結果已寫入 test 表");
        } catch (SQLException e) { e.printStackTrace(); }
    }
}

三、JDBC 事務控制核心 API

方法說明
conn.setAutoCommit(false)關閉自動提交,開啟手動事務控制
conn.commit()提交事務,所有操作持久化
conn.rollback()回滾事務,撤銷所有未提交操作
conn.setTransactionIsolation(level)設定隔離級別 (READ_COMMITTED 等)
stmt.addBatch(sql)將 SQL 加入批次
stmt.executeBatch()批次執行,回傳各條影響列數陣列

四、事務四大特性 (ACID) 速查

  • 原子性:全做或全不做
  • 一致性:事務前後資料庫滿足所有約束
  • 隔離性:並發事務互不干擾
  • 持久性:提交後永久生效

五、事務處理完整範本:批次插入 + 手動提交/回滾

package com.example.jdbc;
import java.sql.*;

public class JdbcTransactionDemo {
    private static final String URL = "jdbc:mysql://localhost:3306/jdbc_test_db";
    private static final String USER = "root", PASS = "896013";

    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(URL, USER, PASS)) {
            conn.setAutoCommit(false);  // 1. 關閉自動提交

            try (Statement stmt = conn.createStatement()) {
                stmt.addBatch("INSERT INTO test(name,age,score) VALUES('haha',10,33)");
                stmt.addBatch("INSERT INTO test(name,age,score) VALUES('heihei',11,44)");
                stmt.addBatch("INSERT INTO test(name,age,score) VALUES('xixi',14,55)");

                int[] results = stmt.executeBatch();  // 2. 批次執行
                System.out.println("批次執行完成,影響列數: " + results.length);

                conn.commit();  // 3. 全部成功 → 提交
                System.out.println("事務提交成功");
            } catch (BatchUpdateException e) {
                System.err.println("批次執行失敗,執行回滾");
                conn.rollback();  // 4. 任一失敗 → 回滾
            }

            conn.setAutoCommit(true);  // 恢復預設
        } catch (SQLException e) { e.printStackTrace(); }
    }
}

六、驗證事務行為

場景程式碼修改資料庫結果
正常提交保留 conn.commit()3 筆資料全部寫入
模擬失敗回滾註解 conn.commit() 或拋出例外0 筆資料寫入 (全數回滾)

七、MySQL 事務注意事項

  • 引擎支援:僅 InnoDB 支援事務,MyISAM 不支援
  • 隱式提交:DDL (CREATE, DROP, ALTER) 會隱式提交當前事務
  • 鎖等待超時:innodb_lock_wait_timeout (預設 50 秒) 超時自動回滾當前陳述式
  • 死鎖:InnoDB 自動偵測並回滾其中一個事務

八、最佳實踐總結

  1. 業務邏輯方法接收 Connection 參數,確保同一事務共用連線
  2. 使用 try-with-resources 管理 Statement/ResultSet,Connection 手動控制關閉時機
  3. catch 區塊務必呼叫 rollback(),finally 關閉連線
  4. 批次操作搭配 addBatch/executeBatch 大幅提升寫入效能
  5. 長事務會持有鎖資源,盡量縮短事務範圍,避免併發衝突

結語:預存程序將商業邏輯下沉至資料庫層,減少網路往返;事務控制保障多步操作的原子性。兩者結合是企業級應用資料一致性的核心保障。掌握 CallableStatement 與手動提交/回滾模式,即可應對大多數複雜業務場景。

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