如何调用 Spring JPA 函数并在对象中返回结果

Posted

技术标签:

【中文标题】如何调用 Spring JPA 函数并在对象中返回结果【英文标题】:How to invoke Spring JPA function and return result in an object 【发布时间】:2021-12-29 18:19:20 【问题描述】:

我在包 PACKAGE_A 中有无法修改的函数 FUNC。我想从 Spring JPA 存储库中调用此函数,但我不知道该怎么做。

功能:

FUNCTION FUNC(
    RESULT_COLUMN_A OUT NUMBER,
    RESULT_COLUMN_B OUT NUMBER,
    RESULT_COLUMN_C OUT VARCHAR
    ) RETURN NUMBER AS
BEGIN
    SELECT COL_1, COL_2, COL_3
    INTO RESULT_COLUMN_A, RESULT_COLUMN_B, RESULT_COLUMN_C 
    FROM DATABASE_TABLE;
    RETURN 0;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RETURN -1;
END;

函数已针对这个问题进行了修改,这不是一个工作场景,但重要的是函数返回三列。

到目前为止我的代码:


@Repository
public class FunctionRepository

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public FuncResponse findFunctionResult() 
        SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                .withCatalogName("PACKAGE_A") //package name
                .withFunctionName("FUNC");
        //First parameter is function output parameter type.
        FuncResponse response = jdbcCall.executeFunction(FuncResponse.class);
        return response;
    

    class FuncResult
        @Column(name = "RESULT_COLUMN_A")
        String resultColumnA;
        String resultColumnB;
        String resultColumnC;
    


当我尝试运行代码时,出现以下异常:

java.sql.SQLException: Missing IN or OUT parameter at index:: 1
    at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:2033) ~[ojdbc11-21.3.0.0.jar:21.3.0.0.0]

更新: 我已经用以下代码更新了,我最初的错误是响应不是数字,而是一个类。所以更新的代码是这样的:


SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                .withCatalogName("PACKAGE_A") //package name
                .withFunctionName("FUNC")
                .declareParameters(new SqlParameter("RESULT_COLUMN_A ", Types.NUMERIC))
                .declareParameters(new SqlParameter("RESULT_COLUMN_B ", Types.NUMERIC))
                .declareParameters(new SqlParameter("RESULT_COLUMN_C ", Types.VARCHAR))
                .withoutProcedureColumnMetaDataAccess();

        //First parameter is function output parameter type.
        Long response = jdbcCall.executeFunction(Long.class);
        if(response == 0)..

问题是它仍然失败并出现异常

java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
    at org.springframework.jdbc.core.metadata.CallMetaDataContext.matchInParameterValuesWithCallParameters(CallMetaDataContext.java:610) 

【问题讨论】:

一个函数可以有 OUT 或 IN OUT 参数,但这是不好的编码习惯。一个函数应该有一个返回值并且没有输出参数。如果你需要一个函数的多个值,你应该使用一个过程。此外,您在我的代码中缺少指定输入参数和输出参数的部分。 【参考方案1】:

听起来您缺少该函数的 in 参数。这是我的一个项目的一个例子。此外,每个函数只能返回一个值,但看起来您正试图在上面的函数中返回多个值。您可能需要仔细检查。

      /*this is at the top of my class. */
  private JdbcTemplate jdbcTemplate;
        static final String ORCL_SCHEMA = "scott";
        static final String ORCL_PKG = "BIGPACKAGE";

            @Override
            public String validateProgCode(String prog, String coas, Date trnsdate) 
                SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate)
             .withSchemaName(ORCL_SCHEMA)
             .withCatalogName(ORCL_PKG)
             .withFunctionName("F_VALIDATEPROGCODE")
             .declareParameters(new SqlParameter("L_PROG", OracleTypes.VARCHAR))
             .declareParameters(new SqlParameter("L_COAS", OracleTypes.VARCHAR))
             .declareParameters(new SqlParameter("TRNSDATE", OracleTypes.DATE));
        
                Map<String, Object> inParams = new HashMap<>();
                inParams.put("L_PROG", prog);
                inParams.put("L_COAS", coas);
                inParams.put("TRNSDATE", trnsdate);
                String validInd = call.executeFunction(String.class, inParams);
                return validInd;
        

这是oracle函数的摘录

 FUNCTION F_ValidateProgCode (L_PROG VARCHAR2, L_COAS VARCHAR2, trnsDate DATE) RETURN
    VARCHAR2 IS
    ....
  end;

【讨论】:

不,我返回一个值,数字,但我有三个 OUT 参数。我已经更新了问题

以上是关于如何调用 Spring JPA 函数并在对象中返回结果的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA:查询如何返回非实体对象或对象列表?

如何从 Spring Data JPA GROUP BY 查询中返回自定义对象

使用 Spring JPA 调用存储过程

如何响应 Spring RestController 返回 ManyToOne 双向 JPA 实体对象?

Spring Data Jpa Specification 调用Oracle 函数/方法

Spring Data Jpa Specification 调用Oracle 函数/方法