Java调用MySQL存储过程详解
在Java中调用MySQL存储过程有多种方式,下面我将详细介绍几种常用的方法。
使用JDBC调用存储过程
基本步骤
- 建立数据库连接
- 创建CallableStatement对象
- 设置参数
- 执行存储过程
- 处理结果
- 关闭资源
示例代码
import java.sql.*;
public class CallStoredProcedureExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/your_database";
String username = "your_username";
String password = "your_password";
Connection conn = null;
CallableStatement cstmt = null;
try {
// 1. 建立连接
conn = DriverManager.getConnection(url, username, password);
// 2. 创建CallableStatement
// 调用无参数的存储过程
// cstmt = conn.prepareCall("{call your_procedure()}");
// 调用带参数的存储过程
cstmt = conn.prepareCall("{call get_employee_by_id(?)}");
// 3. 设置参数
cstmt.setInt(1, 1001); // 设置第一个参数为员工ID 1001
// 4. 执行存储过程
cstmt.execute();
// 5. 处理结果
ResultSet rs = cstmt.getResultSet();
while (rs.next()) {
System.out.println("ID: " + rs.getInt("id"));
System.out.println("Name: " + rs.getString("name"));
System.out.println("Salary: " + rs.getDouble("salary"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6. 关闭资源
try {
if (cstmt != null) cstmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
处理带输出参数的存储过程
如果存储过程有输出参数,需要这样处理:
// 假设存储过程定义如下:
// CREATE PROCEDURE get_employee_count(OUT p_count INT)
// BEGIN
// SELECT COUNT(*) INTO p_count FROM employees;
// END;
CallableStatement cstmt = conn.prepareCall("{call get_employee_count(?)}");
cstmt.registerOutParameter(1, Types.INTEGER); // 注册输出参数
cstmt.execute();
int count = cstmt.getInt(1); // 获取输出参数值
System.out.println("Total employees: " + count);
使用Spring Data JPA调用存储过程
如果使用Spring框架,可以通过JdbcTemplate或SimpleJdbcCall调用存储过程。
使用JdbcTemplate
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.RowMapper;
public class EmployeeDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public Employee getEmployeeById(int id) {
String sql = "{call get_employee_by_id(?)}";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new EmployeeRowMapper());
}
private static class EmployeeRowMapper implements RowMapper<Employee> {
@Override
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
Employee employee = new Employee();
employee.setId(rs.getInt("id"));
employee.setName(rs.getString("name"));
employee.setSalary(rs.getDouble("salary"));
return employee;
}
}
}
使用SimpleJdbcCall
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.core.simple.SimpleJdbcCallOperations;
public class EmployeeDao {
private SimpleJdbcCallOperations simpleJdbcCall;
public void setDataSource(DataSource dataSource) {
this.simpleJdbcCall = new SimpleJdbcCall(dataSource)
.withProcedureName("get_employee_by_id")
.declareParameters(
new SqlParameter("p_id", Types.INTEGER),
new SqlOutParameter("p_name", Types.VARCHAR),
new SqlOutParameter("p_salary", Types.DOUBLE)
);
}
public Map<String, Object> getEmployee(int id) {
Map<String, Object> inParams = new HashMap<>();
inParams.put("p_id", id);
return simpleJdbcCall.execute(inParams);
}
}
使用MyBatis调用存储过程
如果使用MyBatis,可以这样调用:
<!-- Mapper XML -->
<select id="getEmployeeById" statementType="CALLABLE">
{call get_employee_by_id(
#{id, mode=IN, jdbcType=INTEGER},
#{name, mode=OUT, jdbcType=VARCHAR},
#{salary, mode=OUT, jdbcType=DOUBLE}
)}
</select>
// Mapper接口
public interface EmployeeMapper {
Map<String, Object> getEmployeeById(int id);
}
注意事项
- 确保MySQL驱动版本与数据库版本兼容
- 处理异常和关闭资源非常重要
- 对于复杂的存储过程,可能需要处理多个结果集
- 在生产环境中,考虑使用连接池而不是直接创建连接
- 对于大型应用,考虑使用ORM框架如Hibernate或MyBatis简化操作
示例存储过程
MySQL中创建存储过程的示例:
-- 简单查询存储过程
DELIMITER //
CREATE PROCEDURE get_employee_by_id(IN p_id INT)
BEGIN
SELECT id, name, salary FROM employees WHERE id = p_id;
END //
DELIMITER ;
-- 带输出参数的存储过程
DELIMITER //
CREATE PROCEDURE get_employee_count(OUT p_count INT)
BEGIN
SELECT COUNT(*) INTO p_count FROM employees;
END //
DELIMITER ;
就是在Java中调用MySQL存储过程的主要方法,根据你的具体需求和技术栈选择最适合的方式。
