杰瑞科技汇

Java如何调用MySQL存储过程?

Java调用MySQL存储过程详解

在Java中调用MySQL存储过程有多种方式,下面我将详细介绍几种常用的方法。

使用JDBC调用存储过程

基本步骤

  1. 建立数据库连接
  2. 创建CallableStatement对象
  3. 设置参数
  4. 执行存储过程
  5. 处理结果
  6. 关闭资源

示例代码

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);
}

注意事项

  1. 确保MySQL驱动版本与数据库版本兼容
  2. 处理异常和关闭资源非常重要
  3. 对于复杂的存储过程,可能需要处理多个结果集
  4. 在生产环境中,考虑使用连接池而不是直接创建连接
  5. 对于大型应用,考虑使用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存储过程的主要方法,根据你的具体需求和技术栈选择最适合的方式。

分享:
扫描分享到社交APP
上一篇
下一篇