通过' int-jdbc:stored-proc-outbound-gateway'处理存储过程返回值和带有n个返回列的一个/两个游标。

时间:2014-11-06 15:02:41

标签: spring-integration

到目前为止,我能够从前端向存储过程(Oracle)传递n个参数,并从后端接收一个游标(带有n个列)(感谢Gary为他的伟大建议link)。

但是,以下场景仍然无法解决我不仅要尝试接收一个游标(具有n个列)而是返回值以及n个游标(具有n个数量)列)来自后端。我需要帮助:))

到目前为止,我所做的工作如下:

在我的pkg_personalinfo_spring.proc_personalinfo_spring中有以下规范:

procedure proc_personalinfo_spring(
        firstname       in  VARCHAR2,
        lastname        in  VARCHAR2,
        p_RetVal       out  VARCHAR2,           //Previously I was trying without such kind of p_RetVal 'out' variable and it was working. As soon as I added this 
                                                //started   getting exception 
        p_ResultSet    out  sys_refcursor);

在我的存储过程的主体中有这个:

...
p_RetVal := '1';

EXCEPTION WHEN OTHERS THEN p_RetVal := p_RetVal || 'proc_settlement_report: SQLCode: ' || SQLCODE || ' SQL Error Msg: ' || SUBSTR(SQLERRM, 1, 1950); dbms_output.put_line('Error');

  RETURN;
...

现在使用p_RetVal(这是我的返回值)和我的一个光标到目前为止,我做了以下更改:

a)在PersonalinfoDao我为p_RetVal添加了新的getter和setter:

String p_RetVal;

public String getP_RetVal() {
    return p_RetVal;
}

public void setP_RetVal(String p_RetVal) {
    this.p_RetVal = p_RetVal;
}

b)在Mapper类中添加了以下行:

...
PersonalInfo personalInfo = new PersonalInfo();

        try{
            personalInfo.setP_RetVal(resultSet.getString(DBConstants.P_RETVAL));
            feedInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
            feedInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
... 

c)最后在Gateway定义文件中,我有以下更改:

<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->        
    <int-jdbc:stored-proc-outbound-gateway  id="outbound-gateway-storedproc-personalinfo"
                                            request-channel="procedureRequestChannel"
                                            data-source="dataSource"
                                            stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
                                            expect-single-result="true"
                                            ignore-column-meta-data="true"
                                            skip-undeclared-results="true">
        <!-- Parameter Definitions -->                                      
        <int-jdbc:sql-parameter-definition  name="firstname" direction="IN"/>
        <int-jdbc:sql-parameter-definition  name="lastname" direction="IN"/>
        <int-jdbc:sql-parameter-definition name="p_RetVal" type="VARCHAR" direction="OUT"/>
        <int-jdbc:sql-parameter-definition name="get_ResultSet" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>

        <!-- Parameter Mappings Before Passing & Receiving -->                              
        <int-jdbc:parameter name="firstname" expression="payload[0]"/>
        <int-jdbc:parameter name="lastname" expression="payload[1]"/>
        <int-jdbc:returning-resultset name="p_RetVal" row-mapper="com.ge.far.support.FeedinfoMapper"/>
        <int-jdbc:returning-resultset name="get_ResultSet" row-mapper="com.support.PersonalinfoMapper"/>

</int-jdbc:stored-proc-outbound-gateway>

现在,当我运行应用程序时,获得以下例外情况:

...
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:596)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:527)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call PKG_PERSONALINFO_SPRING.PROC_PERSONALINFO_SPRING(?, ?, ?)}]; nested exception is java.sql.SQLException: ORA-06550: line 1, column 3:
PLS-00306: wrong number or types of arguments in call to 'PROC_PERSONALINFO_SPRING'
ORA-06550: line 1, column 3:
PL/SQL: Statement ignored

    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1135)
...
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:170)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
    ... 59 more
Caused by: java.sql.SQLException: ORA-06550: line 1, column 3:
PLS-00306: wrong number or types of arguments in call to 'PROC_PERSONALINFO_SPRING'
ORA-06550: line 1, column 3:
PL/SQL: Statement ignored

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879) 

Plz帮助我找出我在做错的地方。我还需要处理一个情况,即我的结果集中有一个返回变量(如p_RetVal)和n个游标(sys_refcursor)。

再次感谢大家:)

2 个答案:

答案 0 :(得分:1)

由于您的p_RetValVARCHAR OUT参数,因此您无法使用returning-resultset

只需删除<int-jdbc:returning-resultset name="p_RetVal">定义,payload的结果<int-jdbc:stored-proc-outbound-gateway>将包含Map,其中包含两个键:p_RetValStringget_ResultSet List<PersonalInfo>

当然,您应该摆脱DBConstants.P_RETVAL中的PersonalinfoMapperFeedinfoMapper是多余的。

<int-jdbc:returning-resultset>仅适用于CURSOR程序OUT参数。

答案 1 :(得分:1)

好的,经过一些研究后我觉得有一点线索可以解决上述情况。

首先:在我的网关定义文件中,我在'int-jdbc:stored-proc-outbound-gateway'元素中将'expect-single-result'属性的值更改为'false'。这在逻辑上是正确的,因为我的存储过程将返回多个结果集对象。

第二:我在网关定义文件中添加了以下行:

<int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>

目前看起来如下:

<!-- Stored Procedure Outbound-Gateway = To call a database stored procedure -->        
<int-jdbc:stored-proc-outbound-gateway  id="outbound-gateway-storedproc-personalinfo"
                                            request-channel="procedureRequestChannel"
                                            data-source="dataSource"
                                            stored-procedure-name="pkg_personalinfo_spring.proc_personalinfo_spring"
                                            expect-single-result="false"
                                            ignore-column-meta-data="true">
        <!-- Parameter Definitions -->                                      
        <int-jdbc:sql-parameter-definition  name="firstname" direction="IN"/>
        <int-jdbc:sql-parameter-definition  name="lastname" direction="IN"/>
        <int-jdbc:sql-parameter-definition name="p_RetVal" direction="OUT"/>
        <int-jdbc:sql-parameter-definition name="get_ResultSet" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>

        <!-- Parameter Mappings Before Passing & Receiving -->                              
        <int-jdbc:parameter name="firstname" expression="payload[0]"/>
        <int-jdbc:parameter name="lastname" expression="payload[1]"/>
        <int-jdbc:returning-resultset name="get_ResultSet" row-mapper="com.support.PersonalinfoMapper"/>

</int-jdbc:stored-proc-outbound-gateway>

第三:,因为我没有在“传递参数映射”和“传递之前”中定义“p_RetVal”。接收'部分意味着我不会在我的Java代码中使用'p_RetVal'进行映射。因此,我删除了'String p_RetVal;'来自'PersonalinfoDao'及其吸气剂和制定者。

Forth:由于第三步,我还修改了我的Mapper类,如下所示:

...
PersonalInfo personalInfo = new PersonalInfo();

        try{
            feedInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
            feedInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
... 

这就是全部!真???

是的!!! ...但是有一个问题......好吧,直到目前为止,我还不确定我的代码会无异常运行。但是在运行了所有这些小改动的应用程序后,我看到没有异常,所以开始通过'FIDDLER'(我最好的朋友lah;))调试正在发生的事情,我看到后面的JSON对象从后端返回。 Yahoooooooooo ...意味着Spring Integration正在采取行动:)

JSON
  - {}
     -  p_ResultSet
     -   -{}
     -     -    firstname=Faisal
     -     -    lastname=Quazi
     -  p_RetVal=1

现在,抓住你已经注意到在网关定义文件中我在'参数定义'下定义了'p_RetVal',我没有在'参数映射前传递&amp;接收'。这部分我仍然不确定为什么或它如何在后台工作。

所以在这个时刻,你可以认为我的这个答案不是最终的解决方案,但可以接受它作为绕过僵局的情况。 Spring Integration专家可能对此有一些好的发言权:))