Spring Batch StoredProcedureItemReader仅使用输出参数读取StoredProc(无输入参数)

时间:2016-05-17 20:55:31

标签: java spring spring-mvc spring-batch spring-batch-admin

我的SP只有4个输出参数并且没有输入参数,而我的StoredProcedureItemReader conf看起来像这样

<bean id="spItemReader">
    class="org.springframework.batch.item.database.StoredProcedureItemReader" >
    <property name="dataSource" ref="dataSource"/>
    <property name="procedureName" value="mynamespace.spname"/>
    <property name="refCursorPosition" value="1"></property>
    <property name="rowMapper">
        <bean class="MyRowMapper"/>
    </property>
    <property name="parameters">
        <list>
            <bean class="org.springframework.jdbc.core.SqlParameter">
                <constructor-arg index="0" value="column1"/>
                <constructor-arg index="1">
                    <util:constant static-field="java.sql.Types.SMALLINT"/>
                </constructor-arg>
            </bean>
            <bean class="org.springframework.jdbc.core.SqlParameter">
                <constructor-arg index="0" value="P_column2"/>
                <constructor-arg index="1">
                    <util:constant static-field="java.sql.Types.VARCHAR"/>
                </constructor-arg>
            </bean>
            <bean class="org.springframework.jdbc.core.SqlParameter">
                <constructor-arg index="0" value="P_column3"/>
                <constructor-arg index="1">
                    <util:constant static-field="java.sql.Types.INTEGER"/>
                </constructor-arg>
            </bean>
            <bean class="org.springframework.jdbc.core.SqlParameter">
                <constructor-arg index="0" value="P_column4"/>
                <constructor-arg index="1">
                    <util:constant static-field="java.sql.Types.CHAR"/>
                </constructor-arg>
            </bean>
        </list>
    </property>
</bean>

我将dataSource作为org.springframework.jdbc.datasource.DriverManagerDataSource的实例,并以DB2作为驱动程序类连接到com.ibm.db2.jcc.DB2Driver

我的工作配置如下:

<job id="testJob" xmlns="http://www.springframework.org/schema/batch">
    <step id="step1">
        <tasklet>
            <chunk reader="spItemReader" writer="eventItemWriter"
                commit-interval="1" />
        </tasklet>
    </step>
</job>

<bean id="jobRepository"
    class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
    <property name="transactionManager" ref="transactionManager" />
</bean>

<bean id="transactionManager"
    class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />

<bean id="jobLauncher"
    class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
</bean>

我有作家StaxEventItemWriter和正确的unmarshaller配置。

问题是当我运行批处理时,我不断得到:

  

引起:org.springframework.jdbc.BadSqlGrammarException:执行存储过程;错误的SQL语法[{call mynamespace.spname(?,?,?,?)}];嵌套异常是com.ibm.db2.jcc.am.SqlSyntaxErrorException:DB2 SQL错误:SQLCODE = -440,SQLSTATE = 42884,SQLERRMC = PROCEDURE; BSCPROC.PKA109,DRIVER = 4.19.26

我不确定我错过了什么,请建议我该如何解决这个问题。 让我也知道是否需要更多信息。

1 个答案:

答案 0 :(得分:2)

最后我自己找到了解决方案。提供的Spring Batch API StoredProcedureItemReader 提供 PreparedStatementSetter ,必须将其强制转换为 CallableStatement 。因为StoredProcedures不适用于PreparedStatements。我们必须通过为PreparedStatementSetter提供自定义实现来覆盖setValues方法。以下是配置的外观。

注意:属性名称=&#34; preparedStatementSetter&#34; REF =&#34; paramSet&#34;

代码:

<bean id="spItemReader"
 class="org.springframework.batch.item.database.StoredProcedureItemReader" >
<property name="dataSource" ref="dataSource"/>
<property name="procedureName" value="mynamespace.spname"/>
<property name="refCursorPosition" value="1"></property>
 <property name="preparedStatementSetter" ref="paramSet" ></property>  
<property name="rowMapper">
    <bean class="MyRowMapper"/>
</property>
<property name="parameters">
    <list>
        <bean class="org.springframework.jdbc.core.SqlParameter">
            <constructor-arg index="0" value="column1"/>
            <constructor-arg index="1">
                <util:constant static-field="java.sql.Types.SMALLINT"/>
            </constructor-arg>
        </bean>
        <bean class="org.springframework.jdbc.core.SqlParameter">
            <constructor-arg index="0" value="P_column2"/>
            <constructor-arg index="1">
                <util:constant static-field="java.sql.Types.VARCHAR"/>
            </constructor-arg>
        </bean>
        <bean class="org.springframework.jdbc.core.SqlParameter">
            <constructor-arg index="0" value="P_column3"/>
            <constructor-arg index="1">
                <util:constant static-field="java.sql.Types.INTEGER"/>
            </constructor-arg>
        </bean>
        <bean class="org.springframework.jdbc.core.SqlParameter">
            <constructor-arg index="0" value="P_column4"/>
            <constructor-arg index="1">
                <util:constant static-field="java.sql.Types.CHAR"/>
            </constructor-arg>
        </bean>
    </list>
</property>
</bean>

<bean id="paramSet" class="com.jpmc.ib.asup.batch.CustomSPParamSetter" ></bean>

PreparedStatementSetter实现:

代码:

public class CustomSPParamSetter implements PreparedStatementSetter{

@Override
public void setValues(PreparedStatement ps) throws SQLException {

    CallableStatement eventCallableSt=(CallableStatement)ps;
    eventCallableSt.registerOutParameter(1, java.sql.Types.SMALLINT);
    eventCallableSt.registerOutParameter(2, java.sql.Types.VARCHAR);
    eventCallableSt.registerOutParameter(3, java.sql.Types.INTEGER);
    eventCallableSt.registerOutParameter(4, java.sql.Types.CHAR);
}
}

在spring配置文件和PreparedStatementSetter中声明SP参数是不合逻辑的。但这对我来说是正确的工作解决方案。