2014-12-04 29 views
2

我正在構建一個應用程序(使用spring-integration),它應該從任何入站網關接收Request對象並調用MS SQL存儲過程。 請求對象包含String屬性procedureNameList<Pair<String, Object>>屬性parameters。問題是,我無法找到一個解決方案,當我不知道它是編譯時的長度時如何傳遞參數列表。 配置出站網關:stored-proc-outbound-gateway中的參數個數不定

<int-jdbc:stored-proc-outbound-gateway 
     id="outbound-gateway-procedure" request-channel="requestChannel" 
     data-source="dataSource" stored-procedure-name-expression="payload.procedureName" 
     sql-parameter-source-factory="someParameterSourceFactory" > 

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

如果我知道,我已經在列表中2個參數,他們的名字是「第一」和「第二」,我將配置sql-parameter-source-factory的方式是這樣的:

<bean id="someParameterSourceFactory" class="org.springframework.integration.jdbc.ExpressionEvaluatingSqlParameterSourceFactory"> 
    <property name="parameterExpressions"> 
     <map> 
      <entry key="first" value-type="java.lang.String" value="payload.parameters.get(1).second"/> 
      <entry key="second" value-type="java.lang.String" value="payload.parameters.get(2).second"/> 
     </map> 
    </property> 
</bean> 

但我不知道在編譯時沒有數量的參數沒有他們的名字。有什麼建議麼?

UPD: 存儲過程是這樣的:

create procedure [dbo].[pnzLimitUtilization_Show] 
(
    @BookDate   datetime  
    , @LegalGroupList varchar(4000) 
    , @Currency   char(3) 
    , @FilterForAny  nvarchar(255) = '' 
    , @RiskZone   char(1)  = 'A' 
    , @WithZerroExposure char(1)  = '0' 
    , @Transliteration bit   = 0 
    , @IsNewMethodology bit   = 0  
    , @UtilizationType char(1)  = 'A' 
    , @PartyGroupList varchar(255) = NULL    
    , @HostName   varchar(255) = NULL   
    , @ShowCloseExpiration bit = 0 
    , @CloseExpirationDays int = 90 
    , @WhatIfDealFilter char(1)   = 'R'    
    , @HideLESublimits bit   = 0 
) 
as begin .... 

新配置:

<int-jdbc:stored-proc-outbound-gateway 
     id="outbound-gateway-procedure" request-channel="requestChannel" 
     data-source="dataSource" stored-procedure-name-expression="payload.name.toString()" 
     ignore-column-meta-data="true" 
     sql-parameter-source-factory="listParameterSourceFactory" 
     reply-channel="replyChannel"> 
</int-jdbc:stored-proc-outbound-gateway> 

<bean id="listParameterSourceFactory" class="my.pack.integration.ListSqlParameterSourceFactory" /> 

ListSqlParameterSourceFactory:

public class ListSqlParameterSourceFactory implements SqlParameterSourceFactory { 

    @Override 
    @SuppressWarnings("unchecked") 
    public SqlParameterSource createParameterSource(Object input) { 
     GetSourceDataRequest message = (GetSourceDataRequest) input; 
     List<NamedValueEntity> params = message.getParameters(); 
     MapSqlParameterSource source = new MapSqlParameterSource(); 
     for (NamedValueEntity param : params) { 
      source.addValue(param.getName().toString(), param.getValue()); 
     } 
     return source; 
    } 
} 

現在我得到錯誤

Caused by: org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call dbo.pnzLimitUtilization_Show()}]; nested exception is java.sql.SQLException: Procedure or function 'pnzLimitUtilization_Show' expects parameter '@BookDate', which was not supplied. 
    at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:97) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 

我debuged通ListSqlParameterSourceFactory和它的工作如預期,一個SqlParameterSource是

[0] = {[email protected]}"@Currency" -> "R" 
[1] = {[email protected]}"@LegalGroupList" -> "(ALL)" 
[2] = {[email protected]}"@FilterForAny" -> "" 
[3] = {[email protected]}"@ShowCloseExpiration" -> "0" 
[4] = {[email protected]}"@IsNewMethodology" -> "0" 
[5] = {[email protected]}"@CloseExpirationDays" -> "0" 
[6] = {[email protected]}"@WhatIfDealFilter" -> "R" 
[7] = {[email protected]}"@UtilizationType" -> "A" 
[8] = {[email protected]}"@BookDate" -> "20141202 00:00:00.000" 
[9] = {[email protected]}"@Transliteration" -> "0" 
[10] = {[email protected]}"@PartyGroupList" -> "(ALL)" 
[11] = {[email protected]}"@RiskZone" -> "L" 
[12] = {[email protected]}"@HideLESublimits" -> "0" 

有什麼我錯過了嗎?

UPD2: 彈簧JDBC日誌:

05 dec 2014 14:15:28 DEBUG SimpleJdbcCall - Compiled stored procedure. Call string is [{call dbo.pnzLimitUtilization_Show()}] 
05 dec 2014 14:15:28 DEBUG SimpleJdbcCall - SqlCall for procedure [dbo.pnzLimitUtilization_Show] compiled 
05 dec 2014 14:15:28 DEBUG CallMetaDataContext - Matching [@FilterForAny, @BookDate, @Currency, @UtilizationType, @HideLESublimits, @ShowCloseExpiration, @Transliteration, @IsNewMethodology, @RiskZone, @WhatIfDealFilter, @CloseExpirationDays, @PartyGroupList, @LegalGroupList] with [] 
05 dec 2014 14:15:28 DEBUG CallMetaDataContext - Found match for [] 
05 dec 2014 14:15:28 DEBUG SimpleJdbcCall - The following parameters are used for call {call dbo.pnzLimitUtilization_Show()} with: {} 
05 dec 2014 14:15:28 DEBUG JdbcTemplate - Calling stored procedure [{call dbo.pnzLimitUtilization_Show()}] 

看起來它並沒有傳遞任何參數.. 調試CallMetaDataContext我發現this.callParameters是空的。它不是與ignore-column-meta-data="true"連接嗎?但是,如果我切換到false我看到另一個錯誤:

05 dec 2014 14:41:33 DEBUG CallMetaDataProviderFactory - Using org.springframework.jdbc.core.metadata.SqlServerCallMetaDataProvider 
05 dec 2014 14:41:33 DEBUG CallMetaDataProvider - Retrieving metadata for null/null/dbo.pnzLimitUtilization_Show 
05 dec 2014 14:41:36 DEBUG DataSourceUtils - Returning JDBC Connection to DataSource 
org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.integration.jdbc.StoredProcOutboundGateway#0]; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Unable to determine the correct call signature for dbo.pnzLimitUtilization_Show - package name should be specified separately using '.withCatalogName("dbo")' 

UPD3: 好吧,我刪除從參數名稱dbo.從程序名和@,現在可以正確地裝入列的元數據和綁定變量。這並不意味着我的申請有效,但至少我可以走得更遠。阿爾喬姆的建議幫助解決了主要問題。

回答

1

首先你的PROCEDURE是怎麼看的?至少規範。

爲什麼你確定參數的任何列表對您的過程調用都是合法的?

從其他方面你去正確的方式與SqlParameterSourceFactory定製,但它確實應該完全自定義實施。像這樣的事情,因爲你說你的​​有parameters屬性:

public class PairSqlParameterSourceFactory implements SqlParameterSourceFactory { 


    public SqlParameterSource createParameterSource(Object input) { 
     Message<Request> message = (Message<Request>) input; 
     List<Pair<String, Object>> pairs = message.getPayload().getParameters(); 
     MapSqlParameterSource source = new MapSqlParameterSource(); 
     for (Pair<String, Object> pair : pairs) { 
      source.addValue(pair.getName(), pair.getValue()); 
     } 
     return source; 
    } 

} 
+0

嘗試這樣做,但它不仍然工作。你能否看看更新後的帖子? – 2014-12-04 15:39:21

+0

我明白了。你真的錯過了參數的順序。 '@ BookDate'是程序規範中的第一個。但是在你的'SqlParameterSource'中,它位於'[8]'位置。 – 2014-12-04 15:57:51

+0

Artem,但是如果我們深入'MapSqlParameterSource'內部,我們會看到它將參數保存在沒有排序的通常'HashMap'中。來自javadocs:_This類用於將簡單的參數值Map傳遞給NamedParameterJdbcTemplate類的方法。因此,我期望Spring將通過名稱綁定參數。實際上,我按照正確的順序傳遞參數,HashMap完成所有的混亂 – 2014-12-05 08:03:58

相關問題