You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Hibernate调用多输出类型存储过程:临时表映射Java输出值

如何在Java中调用Oracle存储过程并映射自定义表类型输出

你提供的Oracle存储过程属于package_name包,其中输出参数Ind是自定义的关联数组类型(pkg_Type,基于typ记录类型),下面是Java中调用并映射该输出的具体实现步骤:

1. 准备依赖

确保项目中引入适配Oracle版本的JDBC驱动(如ojdbc8或ojdbc11),驱动需要支持Oracle自定义类型的处理。

2. 定义对应Oracle记录类型的Java实体类

对应Oracle中typ记录类型,创建Java实体类来接收每条记录的数据:

public class TypRecord {
    private Integer id;
    private String name;

    public TypRecord() {}

    public TypRecord(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    // getter和setter方法
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

3. 调用存储过程并处理输出参数

使用Oracle JDBC扩展API来处理自定义表类型,示例代码如下:

import oracle.jdbc.OracleConnection;
import oracle.jdbc.OraclePreparedStatement;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;

public class ProcedureCaller {
    public static void main(String[] args) {
        String url = "jdbc:oracle:thin:@//your-oracle-host:port/service-name";
        String user = "your-username";
        String password = "your-password";

        try (Connection conn = DriverManager.getConnection(url, user, password)) {
            // 转换为OracleConnection以使用扩展API
            OracleConnection oracleConn = conn.unwrap(OracleConnection.class);

            // 定义存储过程调用语句
            String callSql = "{ call package_name.procedure_name(?, ?, ?, ?, ?) }";
            OraclePreparedStatement pstmt = (OraclePreparedStatement) oracleConn.prepareCall(callSql);

            // 设置输入参数
            pstmt.setLong(1, 123); // 对应Id参数
            pstmt.setDate(2, Date.valueOf("2024-01-01")); // 对应sDate参数
            pstmt.setDate(3, Date.valueOf("2024-01-31")); // 对应eDate参数

            // 注册输出参数:指定自定义类型的完整名称(包名.类型名)
            pstmt.registerOutParameter(4, oracleConn.getType("PACKAGE_NAME.PKG_TYPE"));
            pstmt.registerOutParameter(5, java.sql.Types.VARCHAR);

            // 执行存储过程
            pstmt.execute();

            // 获取Sol输出参数
            String sol = pstmt.getString(5);
            System.out.println("Sol输出值:" + sol);

            // 获取Ind输出参数(自定义表类型)
            ARRAY indArray = (ARRAY) pstmt.getArray(4);
            // 获取记录类型的描述器
            StructDescriptor structDesc = StructDescriptor.createDescriptor("PACKAGE_NAME.TYP", oracleConn);

            // 将数组转换为STRUCT数组,再映射为Java实体类列表
            Object[] structs = (Object[]) indArray.getArray();
            List<TypRecord> recordList = new ArrayList<>();
            for (Object obj : structs) {
                STRUCT struct = (STRUCT) obj;
                Object[] attrs = struct.getAttributes();
                TypRecord record = new TypRecord((Integer) attrs[0], (String) attrs[1]);
                recordList.add(record);
            }

            // 处理结果列表
            System.out.println("Ind输出的记录列表:");
            for (TypRecord record : recordList) {
                System.out.printf("ID: %d, Name: %s%n", record.getId(), record.getName());
            }

            // 关闭资源
            pstmt.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关键注意事项

  • 类型名称大小写:Oracle默认会将标识符转为大写,所以代码中使用PACKAGE_NAME.PKG_TYPE而非小写的package_name.pkg_type,除非创建类型时用双引号指定了小写名称。
  • 驱动兼容性:确保ojdbc驱动版本与Oracle数据库版本匹配,避免出现类型处理的兼容性问题。
  • 关联数组处理:INDEX BY BINARY_INTEGER的表类型属于Oracle关联数组,JDBC中通过ARRAY类型来接收,需要用StructDescriptor来解析每条记录的结构。

内容的提问来源于stack exchange,提问作者Just a coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 14:32:08