2013-04-09 100 views
1

我使用ItemReader/ItemWriter設置了一個Spring批處理作業,可將數據集從Oracle DB導出到CSV/Excel/PDF。對於閱讀器部分,我使用的是JdbcCursorItemReaderSpring批處理作業參數限制爲250個字符?

默認情況下它是必要的SQL語句傳遞給閱讀器來提取數據集 - 這是我的讀者的配置:

<bean id="readErgebnis" class="org.springframework.batch.item.database.JdbcCursorItemReader" scope="step"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="sql" value="#{jobParameters['stmt']}" /> 
    <property name="rowMapper"> 
     <bean class="myFancyRowMapper" /> 
    </property> 
</bean> 

所以我加入了SQL語句來JobParametersBuilder ...

JobParametersBuilder builder = new JobParametersBuilder(); 
builder.addString("stmt", sql); 

這應該沒問題。但是執行作業失敗,出現SQLException

現在我知道,春天批次記錄一切,它的日誌表,有問題 - 參數字符串(含SQL)被限制在250個字符。見BATCH_JOB_PARAMS表的定義:

CREATE TABLE BATCH_JOB_PARAMS (
    JOB_INSTANCE_ID NUMBER(19,0) NOT NULL , 
    TYPE_CD VARCHAR2(6) NOT NULL , 
    KEY_NAME VARCHAR2(100) NOT NULL , 
    STRING_VAL VARCHAR2(250), 
    DATE_VAL TIMESTAMP DEFAULT NULL , 
    LONG_VAL NUMBER(19,0) , 
    DOUBLE_VAL NUMBER , 
    constraint JOB_INST_PARAMS_FK foreign key (JOB_INSTANCE_ID) 
    references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) 
); 

Spring Batch的商店每一項工作參數在一個新行,因此SQL語句進入STRING_VAL列被限制爲250個字符。我檢查了其他數據庫系統(MySQL和DB2)的DDL,它似乎只限於250個字符。我現在將該欄目更改爲CLOB,工作正常,工作正常。

我的問題:我簡直不能相信,它的目的是通過存儲批處理作業限制在250個字符的工作參數。那麼對於我的方案是否有更好的實現,還是打算更改BATCH_JOB_PARAMS表中參數列的默認值?

+0

不,你不應該修改元數據模式。看到我的迴應。 – Cygnusx1 2013-04-09 15:15:22

回答

3

不要將SQL作爲參數傳遞給作業。相反,創建一個擴展實現InitializingBean的JdbcCursorItemReader的類。

package xxx.readers; 

public class MyReader extends JdbcCursorItemReader<AnObjet> implements InitializingBean{ 


@Override 
public void afterPropertiesSet() throws Exception { 
     // set the SQL 

    String SELECT_PAYMENT = "SELECT * from table" 
    super.setSql(SELECT_PAYMENT); 

    } 
} 

這樣,當Spring在啓動時由spring上下文初始化時,你的sql將被設置。

,如果你需要添加一個WHERE子句,使用PreparedStatementSetter並把它添加到配置。

<bean id="myReader" class="xxx.readers.MyReader"> 
    <property name="dataSource" ref="aDataSource" /> 
    <property name="rowMapper" ref="aMapper" />  
    <property name="preparedStatementSetter" ref="yourPreparedStatementSetter" /> 
</bean> 

一個preparedStatementSetter例如:

package fcdq.iemt.batch.concilliation.utils; 

import java.sql.PreparedStatement; 
import java.sql.SQLException; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.jdbc.core.PreparedStatementSetter; 
import org.springframework.stereotype.Component; 



@Component("aPrStatSetter") 
public class RunNoSetter implements PreparedStatementSetter { 


public void setValues(PreparedStatement ps) throws SQLException { 
    ps.setString(1, "hello"); 
    ps.setString(2, "Hola"); 
    ps.setTimestamp(3, aTimestamp); 
} 
} 

的preparedStatementSetter將在運行時被調用,以取代?在你的where子句中。

希望它有幫助。

+0

謝謝,這是有效的。然而,它更像是一種解決方法,因爲我想記錄已執行的SQL語句 - 而且現在信息丟失了。當然,可以在不同的(自定義)日誌表中記錄該語句。你會推薦還是以另一種方式?除了日誌記錄問題之外,是否還有更多理由不通過SQL作爲參數? – 2013-04-09 16:02:34

+1

我會在文件或其他數據庫中記錄log4j的SQL。 srping的元數據用於控制和了解作業的狀態。例如,如果只傳遞job參數中的SQL,則會發現只能運行一次作業...因爲spring批處理不允許使用相同的參數值運行2作業。多數民衆贊成他如何知道工作是否運行。你的SQL更像是一個步驟參數,然後是一份工作。最後,我想說,通過設計將SQL作爲工作參數傳遞是錯誤的。想象一下,如果你的工作會有10個步驟......你將不得不通過10個SQL! – Cygnusx1 2013-04-09 17:21:18

+0

好點。我的工作是一步一步的,但當然可以隨時改變。 – 2013-04-09 17:41:27

相關問題