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

Java调用Oracle存储过程:如何从对象数组获取单个对象及属性

解决Java调用Oracle存储过程获取对象数组属性的问题

核心原因

你已经成功获取到ARRAY对应的Object[],但Oracle JDBC默认会将数据库自定义OBJECT类型映射为STRUCT实例,而非你定义的Java类,直接强制转换会失败。需要通过正确配置TypeMap,或手动解析STRUCT来访问属性。


方法一:通过TypeMap自动映射到自定义Java类

1. 确保自定义类符合要求

自定义类必须实现SQLData接口,并重写相关方法,对应数据库OBJECT的所有属性:

import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
import java.sql.Date;

public class ExpectedLacDataType implements SQLData {
    // 对应数据库OBJECT的5个属性,变量名建议和数据库字段一致
    private String attr1;
    private Integer attr2;
    private Double attr3;
    private Date attr4;
    private Boolean attr5;

    // 必须提供无参构造函数
    public ExpectedLacDataType() {}

    @Override
    public String getSQLTypeName() throws SQLException {
        // 返回数据库中OBJECT类型的完整名称,例如"XXXXX.T_LAC_TAB_O"
        return "XXXXX.T_LAC_TAB_O";
    }

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        // 严格按照数据库OBJECT属性的定义顺序读取值
        this.attr1 = stream.readString();
        this.attr2 = stream.readInt();
        this.attr3 = stream.readDouble();
        this.attr4 = stream.readDate();
        this.attr5 = stream.readBoolean();
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        // 若无需向数据库写入对象,可留空;如需写入则按顺序写出属性
        stream.writeString(attr1);
        stream.writeInt(attr2);
        stream.writeDouble(attr3);
        stream.writeDate(attr4);
        stream.writeBoolean(attr5);
    }

    // 生成属性的getter方法,用于访问值
    public String getAttr1() { return attr1; }
    public Integer getAttr2() { return attr2; }
    public Double getAttr3() { return attr3; }
    public Date getAttr4() { return attr4; }
    public Boolean getAttr5() { return attr5; }
}

2. 正确配置TypeMap并获取数组

注意:TypeMap必须在执行存储过程、获取ARRAY之前设置,否则不会生效。修改后的代码如下:

// 先配置连接的TypeMap,注册自定义类与数据库OBJECT的映射
Map<String, Class<?>> typeMap = con.getTypeMap();
typeMap.put("XXXXX.T_LAC_TAB_O", ExpectedLacDataType.class);
con.setTypeMap(typeMap);

// 执行存储过程并获取结果
stmt.registerOutParameter(8, Types.ARRAY, "XXXXX.T_LAC_TAB");
stmt.execute();

ARRAY simpleArray = (ARRAY) stmt.getArray(8);
// 此时getArray()会自动将每个STRUCT转换为ExpectedLacDataType实例
ExpectedLacDataType[] values = (ExpectedLacDataType[]) simpleArray.getArray();

// 直接访问属性
for (ExpectedLacDataType item : values) {
    System.out.println("属性1:" + item.getAttr1());
    System.out.println("属性2:" + item.getAttr2());
    // 其他属性依次访问即可
}

方法二:手动解析STRUCT(TypeMap失效时备用)

如果TypeMap配置后仍未生效,可以手动将数组中的Object转换为STRUCT,再读取属性值:

ARRAY simpleArray = (ARRAY) stmt.getArray(8);
Object[] values = (Object[]) simpleArray.getArray();

for (Object obj : values) {
    if (obj instanceof STRUCT) {
        STRUCT struct = (STRUCT) obj;
        // 按数据库OBJECT属性的定义顺序获取值
        Object[] attrs = struct.getAttributes();
        
        String attr1 = (String) attrs[0];
        Integer attr2 = (Integer) attrs[1];
        Double attr3 = (Double) attrs[2];
        Date attr4 = (Date) attrs[3];
        Boolean attr5 = (Boolean) attrs[4];
        
        // 处理属性值
        System.out.println("属性1:" + attr1);
        System.out.println("属性2:" + attr2);
    }
}

内容的提问来源于stack exchange,提问作者Arijit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 23:22:43