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
相关产品推荐
相关产品推荐

