首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

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

     編輯:Java 相關知識

MyBatis 作為主流持久層框架,支援透過 statementType="CALLABLE" 調用資料庫儲存過程。本文從儲存過程基礎概念、優缺點分析、MySQL 語法,到 MyBatis 完整整合範例(含 XML 配置、Mapper 接口、實體類、測試代碼),手把手教你落地實作。

一、儲存過程簡介

儲存過程是一組為完成特定功能的 SQL 語句集,經編譯後儲存在資料庫中。用戶透過名稱與參數調用執行。它可視為資料庫層面的「可程式函數」,封裝業務邏輯,支援流程控制、變數宣告等進階特性。

二、優點

  1. 增強 SQL 功能與靈活性:支援複雜判斷、迴圈、事務控制。
  2. 標準化組件化:建立一次,多處調用;DBA 可獨立優化修改,不影響應用代碼。
  3. 執行速度快:預編譯、執行計劃快取,減少重複解析優化開銷。
  4. 減少網路流量:客戶端只發送呼叫語句,而非大量 SQL 文本。
  5. 安全機制:透過授權 EXECUTE 權限控制資料存取,避免直接暴露資料表。

三、缺點

  1. 維護困難:邏輯變更需修改資料庫物件,版本控制弱。
  2. 擴展性差:業務邏輯分散在應用層與資料庫層,耦合度高。
  3. 人員流失風險:複雜邏輯無文檔時,接手者極難理解。
  4. 效能雙面刃:雖減少網路開銷,但複雜運算佔用資料庫 CPU/IO,可能成瓶頸。

四、MySQL 儲存過程語法速查

4.1 建立

CREATE PROCEDURE sp_name()
BEGIN
    -- SQL 語句
END;

4.2 呼叫

CALL sp_name(); -- 必須加括號,即使無參數

4.3 刪除

DROP PROCEDURE sp_name;

4.4 常用查詢指令

SHOW PROCEDURE STATUS;           -- 列出所有儲存過程基本資訊
SHOW CREATE PROCEDURE sp_name;   -- 顯示特定儲存過程完整定義

五、實戰案例:統計指定名稱設備總數

5.1 建立資料表

DROP TABLE IF EXISTS `cus_device`;
CREATE TABLE `cus_device` (
  `device_sn` VARCHAR(20) NOT NULL COMMENT '設備編號',
  `device_cat_id` INT(1) DEFAULT NULL COMMENT '設備類型',
  `device_name` VARCHAR(64) DEFAULT NULL COMMENT '設備名稱',
  `device_type` VARCHAR(64) DEFAULT NULL COMMENT '設備型號',
  PRIMARY KEY (`device_sn`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

5.2 建立儲存過程(含輸入/輸出參數)

DROP PROCEDURE IF EXISTS `countDevicesName`;
DELIMITER ;;
CREATE PROCEDURE `countDevicesName`(
    IN dName VARCHAR(12),
    OUT deviceCount INT
)
BEGIN
    SELECT COUNT(*) INTO deviceCount FROM cus_device WHERE device_name = dName;
END ;;
DELIMITER ;

說明:IN 為輸入參數,OUT 為輸出參數。DELIMITER 變更語句結束符,避免過程內部 ; 衝突。

5.3 MyBatis 整合配置

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
  </settings>
  <typeAliases>
    <typeAlias type="com.example.DevicePOJO" alias="DevicePOJO"/>
  </typeAliases>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/bms?characterEncoding=GBK"/>
        <property name="username" value="root"/>
        <property name="password" value="123456"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="com/example/DeviceMapper.xml"/>
  </mappers>
</configuration>

實體類 DevicePOJO

public class DevicePOJO {
    private String deviceName;   // 對應 IN 參數
    private Integer deviceCount; // 對應 OUT 參數,建議用包裝類型
    // getter/setter 略
}

DAO 接口

public interface DeviceDAO {
    void count(DevicePOJO devicePOJO);
}

Mapper XML (關鍵點:statementType="CALLABLE")

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.DeviceDAO">
  <select id="count" parameterType="DevicePOJO" statementType="CALLABLE">
    <![CDATA[
      CALL countDevicesName(
        #{deviceName, mode=IN, jdbcType=VARCHAR},
        #{deviceCount, mode=OUT, jdbcType=INTEGER}
      );
    ]]>
  </select>
</mapper>

核心細節:

  • statementType="CALLABLE":告知 MyBatis 執行儲存過程,缺少會拋出 PersistenceException。
  • mode=IN/OUT:對應儲存過程參數方向。
  • jdbcType:需與資料庫欄位類型對應。
  • MyBatis 會自動將 OUT 參數結果回填到傳入物件屬性中。

5.4 單元測試

public class TestProcedure {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            Reader reader = Resources.getResourceAsReader(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        SqlSession session = sqlSessionFactory.openSession();
        DeviceDAO dao = session.getMapper(DeviceDAO.class);
        DevicePOJO device = new DevicePOJO();
        device.setDeviceName("測試設備");
        dao.count(device);
        System.out.println("設備總數:" + device.getDeviceCount());
        session.close();
    }
}

5.5 執行結果

執行結果截圖


透過 CALLABLE 模式,MyBatis 能優雅地整合資料庫儲存過程,適合將高效能、高安全性的核心邏輯下沉至資料庫層。實務上建議:簡單 CRUD 用 MyBatis XML/註解,複雜報表/批次運算考慮儲存過程,並做好版本控管與文檔。

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