到目前为止,我能够从前端将n个参数传递给存储过程(Oracle),并从后端接收一个光标(具有n个列)(感谢Gary的出色建议链接)。
然而,在下面的场景中,我仍然无法解决我试图从后端接收的不仅是一个游标(具有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)
请帮我找出我做错的地方。我还需要处理这样一种情况,即在结果集中有一个返回变量(如p_RetVal
)作为n个游标(sys_refcursor)。
再次感谢大家:)
由于您的p_RetVal
是VARCHAR
OUT
参数,因此不能使用returning-resultset
。
只需移除<int-jdbc:returning-resultset name="p_RetVal">
定义,<int-jdbc:stored-proc-outbound-gateway>
的结果payload
将包含一个具有两个密钥的Map
:p_RetVal
作为String
,get_ResultSet
作为List<PersonalInfo>
。
当然,您应该在PersonalinfoMapper
中去掉DBConstants.P_RETVAL
,而FeedinfoMapper
是多余的。
<int-jdbc:returning-resultset>
仅用于CURSOR
过程OUT
参数。
好的,所以经过一点研究,我认为得到了一点线索,可以解决上述场景。
首先:在我的网关定义文件中,我将"int jdbc:storanted 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>
第三:因为我没有在"传递之前的参数映射&接收"部分,这意味着我不会在Java代码中使用"p_RetVal"进行映射。因此,我删除了"String p_RetVal;"来自"PersonalinfoDao"及其getter和setter。
第四步:由于第三步,我还修改了Mapper类,如下所示:
...
PersonalInfo personalInfo = new PersonalInfo();
try{
feedInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
feedInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
...
仅此而已!真正地
是的!!!。。。但有一个陷阱。。。到目前为止,我还不确定我的代码是否会毫无例外地运行。但在运行了所有这些小更改的应用程序后,我没有看到任何异常,因此通过"FIDDLER"(我最好的朋友lah;))开始了一些调试,在那里我看到了从后端返回的以下JSON对象。哦哦哦哦。。。意味着Spring Integration正在采取行动:)
JSON
- {}
- p_ResultSet
- -{}
- - firstname=Faisal
- - lastname=Quazi
- p_RetVal=1
现在,问题是,正如你已经注意到的那样,在Gateway定义文件中,我在"Parameter Definitions"下定义了"p_RetVal",而在"ParameterMappings Before Passing&正在接收"。这部分我仍然不确定为什么或如何在后台工作。
因此,在这个时刻,你可以认为我的这个答案不是一个最终的解决方案,但可以接受它,认为这是通过打破僵局。Spring集成专家可能对此有很好的发言权:)