目前我正在使用JDBC Spring Integration(非常具体:<int-jdbc:stored-proc-outbound-gateway>
),其中场景将n个参数传递给存储过程(ORACLE)并接收一个返回变量(使用&#39 ; 1&#39;或错误消息)以及可能有n列数的n个CURSORS(sys_refcursor)。
在使用Spring Framework处理上述场景时,我注意到以下问题:
我的前端逻辑是,首先阅读&#39;返回变量&#39;。如果该值为1,则通过将用户重定向到错误页面来开始读取所有CURSORS数据或通过异常。现在,我所有的CURSORS都没有相同数量的列以及相同的长度/类型的数据。在中间层我只有一个Model类来处理所有CURSORS返回元素。这对我来说是一个挑战!
以前我只处理过一个CURSOR。因此在中间层我使用Mapper类将所有CURSOR元素映射到我的Model元素(getter和setter)以将数据推送到前面。但是当使用相同的概念来处理n个CURSORS时 - 这真的是一场噩梦。
让我分享一下我之前做过的事情,以及我后来为了解决这种情况而做出的事情,然后我会在本文的后半部分提出我的理解,这将使得EXPARTS的意见不足。
对于一个返回变量(带有&#39; 1&#39;或错误消息)以及一个CURSOR : 我的网关定义如下:
<!-- 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>
在Mapper类中,我有以下简单的映射规则:
...
PersonalInfo personalInfo = new PersonalInfo();
try{
personalInfo.setFirstname(resultSet.getString(DBConstants.FIRSTNAME));
personalInfo.setLastname(resultSet.getString(DBConstants.LASTNAME));
...
我这样做是因为在我的Model类中,我有所有CURSOR返回元素的getter和setter。
现在,对于一个返回变量(带有&#39; 1&#39;或错误消息)以及 n个CURSORS : 我更改了我的网关定义如下:
<!-- 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_curr_1" type="#{T(oracle.jdbc.OracleTypes).CURSOR}" direction="OUT"/>
<int-jdbc:sql-parameter-definition name="get_curr_2" 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:stored-proc-outbound-gateway>
其次我删除了整个行映射概念,意味着我没有任何Mapper类。我唯一拥有的只有一个Model类,包含所有CURSORS元素名称及其getter和setter。
另请注意,在我的“参数定义”中,如何添加这两个CURSORS定义,但在“传递前的参数映射”和“接收&#39;我现在什么也没有。
我没有任何例外地运行应用程序,后来通过Fiddler观察到RESPOND附带的以下JSON数据,意味着一切都完美! ;)
JSON
- {}
- get_curr_1
- -{}
- - firstname=Faisal
- - lastname=Quazi
- get_curr_2
- -{}
- - country=Bangladesh
- - capital=Dhaka
什么是黑客?是的......我有同样的感受;)
现在,任何人都可以帮助理解这里发生了什么。这是一个真实的陈述&#34;&#39; int-jdbc:stored-proc-outbound-gateway&#39;能够神奇地映射你的模型元素???&#34;
有没有最好的做法来处理这种情况?
总是谢谢你们:)
答案 0 :(得分:1)
:-)。我想默认情况下Spring JDBC使用ColumnMapRowMapper
。
所以你最终会在Map<String, <Map<?, ?>>>
之类的网关之后结束。但无论如何它都是Map
。
由于您进一步将payload
转换为JSON,杰克逊可以完美地处理地图,因此您可以获得正确的结果。
我当然可以debug
,但扣除说它可以有所不同。
<强>更新强>
正如我所说。答案在JdbcTemplate#extractOutputParameters
:
....
if (outParam.isResultSetSupported()) {
returnedResults.putAll(processResultSet((ResultSet) out, outParam));
}
else {
String rsName = outParam.getName();
SqlReturnResultSet rsParam = new SqlReturnResultSet(rsName, new ColumnMapRowMapper());
returnedResults.putAll(processResultSet((ResultSet) out, rsParam));
if (logger.isDebugEnabled()) {
logger.debug("Added default SqlReturnResultSet parameter named '" + rsName + "'");
}
}
....