Spring 批处理 StoredProcedureItemReader 以仅使用输出参数(无输入参数)读取 StoredProc
Spring Batch StoredProcedureItemReader to read StoredProc with only output parameters(no input Params)
我的 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>
我将数据源作为 org.springframework.jdbc.datasource.DriverManagerDataSource
的实例,并使用 com.ibm.db2.jcc.DB2Driver
作为驱动程序连接到 DB2
class。
我的作业配置如下:
<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
配置。
问题是当我 运行 批次时,我不断收到:
Caused by: org.springframework.jdbc.BadSqlGrammarException: Executing stored procedure; bad SQL grammar [{call mynamespace.spname(?, ?, ?, ?)}]; nested exception is com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=PROCEDURE;BSCPROC.PKA109, DRIVER=4.19.26
我不确定我遗漏了什么,请指教我应该如何解决这个问题。
如果需要更多信息,也请告诉我。
终于我自己找到了解决办法。 Spring 批处理 API 提供 StoredProcedureItemReader 提供 PreparedStatementSetter,必须将其类型转换为 CallableStatement。因为 StoredProcedures 不能与 PreparedStatements 一起使用。我们将不得不通过为 PreparedStatementSetter 提供自定义实现来覆盖 setValues 方法。这是配置的外观。
注:属性 名称="preparedStatementSetter" 参考="paramSet"
代码:
<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 参数是不合逻辑的。但这对我来说是正确的工作解决方案。
我的 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>
我将数据源作为 org.springframework.jdbc.datasource.DriverManagerDataSource
的实例,并使用 com.ibm.db2.jcc.DB2Driver
作为驱动程序连接到 DB2
class。
我的作业配置如下:
<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
配置。
问题是当我 运行 批次时,我不断收到:
Caused by: org.springframework.jdbc.BadSqlGrammarException: Executing stored procedure; bad SQL grammar [{call mynamespace.spname(?, ?, ?, ?)}]; nested exception is com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-440, SQLSTATE=42884, SQLERRMC=PROCEDURE;BSCPROC.PKA109, DRIVER=4.19.26
我不确定我遗漏了什么,请指教我应该如何解决这个问题。 如果需要更多信息,也请告诉我。
终于我自己找到了解决办法。 Spring 批处理 API 提供 StoredProcedureItemReader 提供 PreparedStatementSetter,必须将其类型转换为 CallableStatement。因为 StoredProcedures 不能与 PreparedStatements 一起使用。我们将不得不通过为 PreparedStatementSetter 提供自定义实现来覆盖 setValues 方法。这是配置的外观。
注:属性 名称="preparedStatementSetter" 参考="paramSet"
代码:
<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 参数是不合逻辑的。但这对我来说是正确的工作解决方案。