Java调用MySQL存储过程核心是CallableStatement,必须按{CALL proc_name(?, ?, ?)}格式调用,严格遵循registerOutParameter→execute→getXxx三步操作,参数顺序、类型、方向须与MySQL端声明完全一致。

Java 中用 JDBC 调用 MySQL 存储过程,核心是使用 CallableStatement,它专为执行 SQL 存储过程和函数设计。关键在于正确注册输出参数、设置输入参数,并按 MySQL 的语法格式写调用语句。
1. 确保 MySQL 存储过程已创建且可被 JDBC 访问
MySQL 存储过程需在数据库中存在,且连接用户有 EXECUTE 权限。注意:MySQL 8.0+ 默认开启 sql_mode 中的 STRICT_TRANS_TABLES 等限制,建议创建时显式指定 DEFINER 或使用当前用户,避免权限或上下文问题。
例如创建一个带输入、输出、输入输出参数的简单过程:
DELIMITER $$
CREATE PROCEDURE sp_test(
IN p_in INT,
OUT p_out VARCHAR(50),
INOUT p_inout DECIMAL(10,2)
)
BEGIN
SET p_out = CONCAT('Result for ', p_in);
SET p_inout = p_inout * 2;
END$$
DELIMITER ;2. 使用 CallableStatement 正确调用(含参数绑定)
JDBC 调用 MySQL 存储过程必须用 {CALL proc_name(?, ?, ?)} 格式(不能用 SELECT 或直接语句),且所有参数(包括 OUT/INOUT)都必须通过 registerOutParameter() 声明类型。
立即学习“Java免费学习笔记(深入)”;
示例代码(使用 try-with-resources):
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
String sql = "{CALL sp_test(?, ?, ?)}";
try (Connection conn = DriverManager.getConnection(url, user, pwd);
CallableStatement cs = conn.prepareCall(sql)) {
<pre class="brush:php;toolbar:false;">// 设置 IN 参数(索引从 1 开始)
cs.setInt(1, 123);
// 注册 OUT 和 INOUT 参数(必须在 execute 前调用)
cs.registerOutParameter(2, Types.VARCHAR); // p_out
cs.registerOutParameter(3, Types.DECIMAL); // p_inout
// 执行(不返回 ResultSet,用 execute() 即可)
cs.execute();
// 获取输出值
String resultOut = cs.getString(2);
BigDecimal resultInout = cs.getBigDecimal(3);
System.out.println("p_out = " + resultOut); // "Result for 123"
System.out.println("p_inout = " + resultInout); // 原值 × 2}
注意:未调用 registerOutParameter() 就直接 getXXX() 会抛 SQLException;execute() 比 executeQuery() 更通用,尤其对无结果集的过程。
3. 处理带结果集的存储过程(SELECT 语句)
若存储过程中包含 SELECT(如 SELECT id, name FROM users WHERE age > ?;),JDBC 会将其作为隐式结果集返回。此时需用 execute() 启动,再用 getResultSet() 获取:
String sql = "{CALL sp_get_users(?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
cs.setInt(1, 18);
<pre class="brush:php;toolbar:false;">boolean hasResultSet = cs.execute(); // 返回 true 表示第一个结果是 ResultSet
if (hasResultSet) {
try (ResultSet rs = cs.getResultSet()) {
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
}
}
// 若还有更多结果(多 SELECT),用 cs.getMoreResults() 循环获取}
4. 注意 MySQL 特定配置与常见坑
MySQL JDBC 驱动(Connector/J)默认不支持多结果集和 OUT 参数,需在连接 URL 中显式启用:
- 添加
allowMultiQueries=true(仅当过程内含多个语句) - 确保
useServerPrepStmts=false(MySQL 旧版驱动中,服务端预编译可能干扰 OUT 参数) - 推荐连接 URL 示例:
jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&allowMultiQueries=true&useServerPrepStmts=false - 驱动版本建议用 8.0.28+(对存储过程兼容性更好,修复了早期版本中
registerOutParameter类型映射异常等问题)
另外,MySQL 的 OUT 参数值在 execute() 后才可用,不能在执行前读取;INOUT 参数需先设初值再注册,否则部分驱动可能报空指针。

















