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

Spring Data JPA调用Oracle存储过程返回多参数报错求助

问题分析与解决方案

你的错误根源在于:Spring Data JPA的@Procedure注解直接返回Map时,不会自动将REF_CURSOR类型的输出参数转换为CustomerEntity实体列表,而是返回原始的JDBC ResultSet对象。这个对象内部关联了JDBC Statement、Connection等资源,Jackson序列化时会触发循环引用,导致报错。

Spring Data JPA支持调用带多个输出参数(包括REF_CURSOR)的Oracle存储过程,但需要调整实现方式,避免直接返回包含JDBC底层对象的Map。

正确实现步骤

1. 定义返回结果DTO

创建一个自定义DTO来封装所有输出参数,避免使用Map导致序列化问题:

public class CustResultDTO {
    private String localCode;
    private List<CustomerEntity> customers;

    // 构造器、getter、setter方法
    public CustResultDTO(String localCode, List<CustomerEntity> customers) {
        this.localCode = localCode;
        this.customers = customers;
    }

    // 省略getter和setter
}

2. 调整Repository结构

通过自定义Repository接口+实现类的方式,手动处理存储过程调用:

// 主Repository接口
@Repository
public interface CustomerRepositoryExt extends JpaRepository<CustomerEntity, Long>, CustomerRepositoryExtCustom {
}

// 自定义方法接口
public interface CustomerRepositoryExtCustom {
    CustResultDTO getCust(String username);
}

// 实现类
@Repository
public class CustomerRepositoryExtImpl implements CustomerRepositoryExtCustom {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public CustResultDTO getCust(String username) {
        // 调用命名存储过程
        StoredProcedureQuery query = entityManager.createNamedStoredProcedureQuery("Ent.getCust");
        // 设置输入参数
        query.setParameter("p_username", username);
        
        // 执行存储过程
        query.execute();
        
        // 获取普通OUT参数
        String localCode = (String) query.getOutputParameterValue("o_local_code");
        // 获取REF_CURSOR结果并转换为实体列表
        List<CustomerEntity> customers = query.getResultList();
        
        // 封装结果返回
        return new CustResultDTO(localCode, customers);
    }
}

3. 原实体类注解无需修改

你当前的@NamedStoredProcedureQuery配置是正确的,REF_CURSOR参数的type = Void.class符合Oracle的配置要求,不需要调整。

为什么原写法会报错?

原Repository方法返回Map<String, CustomerEntity>存在两个问题:

  • REF_CURSOR对应的o_result是结果集,不是单个CustomerEntity,类型不匹配;
  • Spring Data JPA的@Procedure注解无法自动将REF_CURSOR的ResultSet转换为实体列表,返回的ResultSet包含JDBC底层资源(如Connection),Jackson序列化时会触发循环引用链,导致转换失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:09:24