org.springframework.jdbc.object.StoredProcedure 繼承 SqlCall(提供 CallableStatementCreator 底層支援),是抽象類,需子類化封裝具體存儲過程調用。
CREATE PROCEDURE CountTable(IN tableName varchar(1000), OUT sqlStr varchar(1000), INOUT v INT)
BEGIN
SET @flag = v;
SET @sql = CONCAT('select count(*) into @res from ', tableName, ' where ACTIVE_FLAG=?');
PREPARE stmt FROM @sql;
EXECUTE stmt USING @flag;
DEALLOCATE PREPARE stmt;
SET v = @res;
SET sqlStr = @sql;
END
public class CountTableStoredProcedure extends StoredProcedure {
private static final String PROC_NAME = "CountTable";
public static final String IN_PARAM = "tableName";
public static final String OUT_PARAM = "sqlStr";
public static final String INOUT_PARAM = "v";
public CountTableStoredProcedure(DataSource ds) {
super(ds, PROC_NAME);
// setFunction(true); // 若為 FUNCTION 則啟用
declareParameter(new SqlParameter(IN_PARAM, Types.VARCHAR));
declareParameter(new SqlOutParameter(OUT_PARAM, Types.VARCHAR));
declareParameter(new SqlInOutParameter(INOUT_PARAM, Types.INTEGER));
compile(); // 必須調用,構建底層 CallableStatement
}
public CountTableResult doCountTable(String tableName, Integer v) {
Map inMap = new HashMap<>();
inMap.put(IN_PARAM, tableName);
inMap.put(INOUT_PARAM, v);
Map outMap = execute(inMap);
CountTableResult result = new CountTableResult();
result.setSql((String) outMap.get(OUT_PARAM));
result.setCount((Integer) outMap.get(INOUT_PARAM));
return result; // 強類型結果對象,而非原始 Map
}
}
compile() 會自動生成標準調用語法 {call CountTable(?,?,?)}SqlParameter/SqlOutParameter/SqlInOutParameterdeclareParameter 時指定的名稱完全一致,建議定義為常量setFunction(true)CountTableStoredProcedure proc = new CountTableStoredProcedure(dataSource);
CountTableResult result = proc.doCountTable("my_table", 1);
// 直接使用 result.getSql(), result.getCount()
當構造輸入參數需要 Connection 時(如 Oracle ARRAY 類型),使用 execute(ParameterMapper):
public Map callOracleArrayProc() {
ParameterMapper mapper = new ParameterMapper() {
public Map createMap(Connection con) throws SQLException {
Map in = new HashMap();
Integer[] arr = {1, 2};
ArrayDescriptor desc = new ArrayDescriptor("NUMBERS", con);
ARRAY oracleArray = new ARRAY(desc, con, arr);
in.put("arrayParam", oracleArray);
return in;
}
};
return execute(mapper);
}
普通場景下 execute(Map) 更簡潔,ParameterMapper 為特殊數據類型提供底層連接訪問能力。