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

MyBatis 調用存儲過程完整教程:IN/OUT 參數映射與參數映射器配置

     編輯:Java 相關知識

數據庫準備

CREATE TABLE p_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(20),
    sex CHAR(1)  -- '男' 或 '女'
);

INSERT INTO p_user(name, sex) VALUES('A', '男');
INSERT INTO p_user(name, sex) VALUES('B', '女');
INSERT INTO p_user(name, sex) VALUES('C', '男');

-- 存儲過程:統計性別人數
DELIMITER $
CREATE PROCEDURE ges_user_count(IN sex_id INT, OUT user_count INT)
BEGIN
    IF sex_id = 0 THEN
        SELECT COUNT(*) FROM p_user WHERE sex = '女' INTO user_count;
    ELSE
        SELECT COUNT(*) FROM p_user WHERE sex = '男' INTO user_count;
    END IF;
END $
DELIMITER ;

-- 測試調用
SET @user_count = 0;
CALL ges_user_count(0, @user_count);
SELECT @user_count; -- 返回 1

Mapper XML 配置

<mapper namespace="me.gacl.mapping.userMapper">
    <!-- statementType="CALLABLE" 聲明調用存儲過程 -->
    <select id="getUserCount" statementType="CALLABLE" parameterMap="countParamMap">
        CALL ges_user_count(?, ?)
    </select>
    
    <!-- 參數映射:IN/OUT 方向、JDBC 類型 -->
    <parameterMap id="countParamMap" type="java.util.Map">
        <parameter property="sexid" mode="IN" jdbcType="INTEGER"/>
        <parameter property="usercount" mode="OUT" jdbcType="INTEGER"/>
    </parameterMap>
</mapper>

Java 調用代碼

public class StoredProcTest {
    @Test
    public void testGetUserCount() {
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        String statement = "me.gacl.mapping.userMapper.getUserCount";
        
        // 必須使用 Map 傳遞 IN/OUT 參數
        Map<String, Integer> paramMap = new HashMap<>();
        paramMap.put("sexid", 0);      // IN 參數:0=女, 1=男
        paramMap.put("usercount", -1); // OUT 參數:初始值任意
        
        // 執行調用(返回值通常為 null,結果在 paramMap 中)
        sqlSession.selectOne(statement, paramMap);
        
        // 獲取 OUT 參數結果
        Integer result = paramMap.get("usercount");
        System.out.println("統計結果: " + result); // 輸出 1
        
        sqlSession.close();
    }
}

關鍵點總結

  1. statementType="CALLABLE":告訴 MyBatis 這是存儲過程調用,而非普通 SELECT
  2. parameterMap 而非 parameterType:存儲過程需精確控制 IN/OUT/INOUT 方向,Map 類型承載多參數
  3. mode 屬性:IN(輸入)、OUT(輸出)、INOUT(雙向)
  4. jdbcType:匹配數據庫參數類型(INTEGER、VARCHAR 等)
  5. 佔位符順序:CALL proc(?, ?) 順序必須與 parameterMap 定義順序一致

進階:複雜類型 OUT 參數

若存儲過程返回結果集(REF CURSOR),需配合 resultMap 映射:

<select id="getUsers" statementType="CALLABLE" resultMap="userMap">
    CALL get_users(?, ?)
</select>
<parameterMap id="procParams" type="map">
    <parameter property="deptId" mode="IN" jdbcType="INTEGER"/>
    <parameter property="cursor" mode="OUT" jdbcType="CURSOR" 
              javaType="java.sql.ResultSet" resultMap="userMap"/>
</parameterMap>

注意:不同數據庫對游標支持不同(Oracle 支持良好,MySQL 需 8.0+ 且配置特定驅動)。

優缺點評估

優點缺點
業務邏輯下沉數據庫,減少網絡交互業務邏輯分散,難以版本控制與單元測試
複雜統計/報表性能優於多次查詢數據庫鎖定時間長,影響併發
利用數據庫原生能力(臨時表、窗口函數)移植性差,綁定特定數據庫方言

建議:核心業務邏輯保持在 Java 層,僅在極度複雜的統計報表、批量數據處理場景考慮存儲過程。

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