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

Spring Boot调用含Table/TableType入参出参存储过程报错如何解决

该Cannot convert SQL type TABLE to Java type java.lang.Object报错的核心原因是Spring Data JPA/JDBC的默认类型转换器未适配数据库自定义的TABLE类型,无法直接完成SQL TABLE类型到Java对象的映射,可按以下步骤解决:

解决步骤

1. 定义与TABLE类型结构匹配的Java POJO

确保POJO字段的顺序、数据类型和数据库中定义的TABLE类型字段完全对应,示例如下:

// 对应数据库定义 TYPE user_table AS TABLE(id INT, name VARCHAR(20))
public class UserTableItem {
    private Integer id;
    private String name;

    // 全参构造方法
    public UserTableItem(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    // getter、setter方法省略
}

2. 自定义TABLE类型的映射处理器

实现SqlReturnType接口完成出参的TABLE类型到JavaList<POJO>的转换,示例如下:

public class TableTypeReturnType implements SqlReturnType {
    @Override
    public Object getTypeValue(CallableStatement cs, int paramIndex, int sqlType, String typeName) throws SQLException {
        Array array = cs.getArray(paramIndex);
        Object[] structs = (Object[]) array.getArray();
        List<UserTableItem> result = new ArrayList<>();
        for (Object struct : structs) {
            Struct s = (Struct) struct;
            Object[] attrs = s.getAttributes();
            // 按TABLE类型字段顺序取值映射到POJO
            result.add(new UserTableItem((Integer) attrs[0], (String) attrs[1]));
        }
        return result;
    }
}

3. 手动配置存储过程调用参数

不要使用@Procedure注解的默认自动映射,改用SimpleJdbcCall手动指定TABLE类型参数的类型和处理器,示例如下:

@Autowired
private JdbcTemplate jdbcTemplate;

public List<UserTableItem> callProcedureWithTableType(List<UserTableItem> inputList) throws SQLException {
    // 初始化存储过程调用对象
    SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
            .withProcedureName("你的存储过程名称")
            .declareParameters(
                    // 声明入参:参数名、类型为ARRAY、对应数据库的TABLE类型名
                    new SqlParameter("in_table_param", Types.ARRAY, "USER_TABLE"),
                    // 声明出参:参数名、类型为ARRAY、对应数据库的TABLE类型名、指定自定义处理器
                    new SqlOutParameter("out_table_param", Types.ARRAY, "USER_TABLE", new TableTypeReturnType())
            );

    // 构造入参TABLE对应的数据结构
    Connection connection = jdbcTemplate.getDataSource().getConnection();
    Object[] structArray = inputList.stream()
            .map(item -> {
                try {
                    return connection.createStruct("USER_TABLE", new Object[]{item.getId(), item.getName()});
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            })
            .toArray();
    Array inputArray = connection.createArrayOf("USER_TABLE", structArray);

    // 执行调用获取返回结果
    Map<String, Object> params = new HashMap<>();
    params.put("in_table_param", inputArray);
    Map<String, Object> resultMap = jdbcCall.execute(params);
    List<UserTableItem> outputList = (List<UserTableItem>) resultMap.get("out_table_param");

    // 关闭临时连接避免泄漏
    connection.close();
    return outputList;
}

4. 适配不同数据库的特殊实现

  • Oracle数据库的嵌套表/VARRAY类型,需替换示例中的Array/Struct为Oracle驱动对应的ARRAY/STRUCT实现类
  • PostgreSQL的复合类型数组,需使用驱动包中的PGobject完成结构映射
  • Hibernate 6+版本原生支持结构化用户自定义类型,可通过@UserDefinedType注解简化配置,无需手动编写类型处理器
注意事项
  • 数据库TABLE类型的字段顺序必须和POJO映射时的取值顺序完全一致,否则会出现类型转换异常或者数据错位
  • 调用过程中手动获取的连接必须显式关闭,避免数据库连接池资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:39:04