杰瑞科技汇

Java如何调用Oracle存储过程?

Java调用Oracle存储过程详解

在Java应用程序中调用Oracle存储过程是一个常见的任务,下面我将详细介绍几种常用的方法。

Java如何调用Oracle存储过程?-图1
(图片来源网络,侵删)

基本概念

Oracle存储过程是存储在数据库中的一段PL/SQL代码,可以通过Java程序调用并传递参数,Java调用存储过程主要通过JDBC(Java Database Connectivity)实现。

调用无参数的存储过程

import java.sql.*;
public class CallStoredProcedureExample {
    public static void main(String[] args) {
        // 数据库连接信息
        String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
        String user = "username";
        String password = "password";
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            // 创建CallableStatement对象
            CallableStatement cstmt = conn.prepareCall("{call procedure_name()}");
            // 执行存储过程
            cstmt.execute();
            System.out.println("存储过程执行成功");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

调用带输入参数的存储过程

// 假设存储过程定义为: PROCEDURE add_emp (emp_id IN NUMBER, emp_name IN VARCHAR2)
try (Connection conn = DriverManager.getConnection(url, user, password)) {
    CallableStatement cstmt = conn.prepareCall("{call add_emp(?, ?)}");
    // 设置输入参数
    cstmt.setInt(1, 1001); // 第一个参数
    cstmt.setString(2, "John Doe"); // 第二个参数
    cstmt.execute();
    System.out.println("添加员工成功");
} catch (SQLException e) {
    e.printStackTrace();
}

调用带输出参数的存储过程

// 假设存储过程定义为: PROCEDURE get_emp_name (emp_id IN NUMBER, emp_name OUT VARCHAR2)
try (Connection conn = DriverManager.getConnection(url, user, password)) {
    CallableStatement cstmt = conn.prepareCall("{call get_emp_name(?, ?)}");
    // 设置输入参数
    cstmt.setInt(1, 1001);
    // 注册输出参数
    cstmt.registerOutParameter(2, Types.VARCHAR);
    cstmt.execute();
    // 获取输出参数
    String empName = cstmt.getString(2);
    System.out.println("员工姓名: " + empName);
} catch (SQLException e) {
    e.printStackTrace();
}

调用带输入输出参数的存储过程

// 假设存储过程定义为: PROCEDURE update_salary (emp_id IN NUMBER, new_salary IN OUT NUMBER)
try (Connection conn = DriverManager.getConnection(url, user, password)) {
    CallableStatement cstmt = conn.prepareCall("{call update_salary(?, ?)}");
    // 设置输入参数
    cstmt.setInt(1, 1001);
    cstmt.setDouble(2, 5000.00); // 初始值
    // 注册输入输出参数
    cstmt.registerOutParameter(2, Types.NUMERIC);
    cstmt.execute();
    // 获取修改后的值
    double updatedSalary = cstmt.getDouble(2);
    System.out.println("更新后的薪资: " + updatedSalary);
} catch (SQLException e) {
    e.printStackTrace();
}

调用返回结果集的存储过程

Oracle存储过程可以通过REF CURSOR返回结果集,Java中需要使用Oracle特定的类型来处理:

import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleTypes;
// 假设存储过程定义为: PROCEDURE get_emps_by_dept (dept_id IN NUMBER, emp_cursor OUT SYS_REFCURSOR)
try (Connection conn = DriverManager.getConnection(url, user, password)) {
    // 需要转换为OracleConnection才能创建OracleCallableStatement
    OracleConnection oraConn = conn.unwrap(OracleConnection.class);
    CallableStatement cstmt = oraConn.prepareCall("{call get_emps_by_dept(?, ?)}");
    // 设置输入参数
    cstmt.setInt(1, 10);
    // 注册输出参数为REF CURSOR
    cstmt.registerOutParameter(2, OracleTypes.CURSOR);
    cstmt.execute();
    // 获取结果集
    ResultSet rs = ((OracleCallableStatement)cstmt).getCursor(2);
    // 处理结果集
    while (rs.next()) {
        System.out.println("ID: " + rs.getInt("emp_id") + 
                          ", Name: " + rs.getString("emp_name"));
    }
    rs.close();
} catch (SQLException e) {
    e.printStackTrace();
}

最佳实践

  1. 使用try-with-resources:确保Connection、Statement和ResultSet等资源被正确关闭
  2. 参数化查询:始终使用参数化查询而非字符串拼接,防止SQL注入
  3. 错误处理:妥善处理SQLException
  4. 连接池:在生产环境中使用连接池(如HikariCP)提高性能
  5. 批处理:对于大量调用,考虑使用批处理提高效率

完整示例

import java.sql.*;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleTypes;
public class OracleStoredProcedureExample {
    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:@localhost:1521:ORCL";
        String user = "username";
        String password = "password";
        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            // 示例1: 调用无参数存储过程
            callSimpleProcedure(conn);
            // 示例2: 调用带输入参数的存储过程
            callProcedureWithInput(conn, 1001, "John Doe");
            // 示例3: 调用带输出参数的存储过程
            callProcedureWithOutput(conn, 1001);
            // 示例4: 调用返回结果集的存储过程
            callProcedureWithResultSet(conn, 10);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    // 无参数存储过程
    private static void callSimpleProcedure(Connection conn) throws SQLException {
        try (CallableStatement cstmt = conn.prepareCall("{call simple_procedure()}")) {
            cstmt.execute();
            System.out.println("简单存储过程执行成功");
        }
    }
    // 带输入参数的存储过程
    private static void callProcedureWithInput(Connection conn, int empId, String empName) throws SQLException {
        try (CallableStatement cstmt = conn.prepareCall("{call add_emp(?, ?)}")) {
            cstmt.setInt(1, empId);
            cstmt.setString(2, empName);
            cstmt.execute();
            System.out.println("添加员工成功");
        }
    }
    // 带输出参数的存储过程
    private static void callProcedureWithOutput(Connection conn, int empId) throws SQLException {
        try (CallableStatement cstmt = conn.prepareCall("{call get_emp_name(?, ?)}")) {
            cstmt.setInt(1, empId);
            cstmt.registerOutParameter(2, Types.VARCHAR);
            cstmt.execute();
            String empName = cstmt.getString(2);
            System.out.println("员工ID: " + empId + ", 姓名: " + empName);
        }
    }
    // 返回结果集的存储过程
    private static void callProcedureWithResultSet(Connection conn, int deptId) throws SQLException {
        OracleConnection oraConn = conn.unwrap(OracleConnection.class);
        try (CallableStatement cstmt = oraConn.prepareCall("{call get_emps_by_dept(?, ?)}")) {
            cstmt.setInt(1, deptId);
            cstmt.registerOutParameter(2, OracleTypes.CURSOR);
            cstmt.execute();
            try (ResultSet rs = ((OracleCallableStatement)cstmt).getCursor(2)) {
                System.out.println("部门 " + deptId + " 的员工:");
                while (rs.next()) {
                    System.out.println("ID: " + rs.getInt("emp_id") + 
                                     ", Name: " + rs.getString("emp_name"));
                }
            }
        }
    }
}

通过以上示例,你应该能够掌握在Java中调用Oracle存储过程的各种方法,根据你的具体需求选择合适的方式实现。

Java如何调用Oracle存储过程?-图2
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇