我一直在尝试弹簧批量示例,我无法通过itemwriter
删除数据库中的记录。 itemreader
工作正常,但在itemwriter
我不知道如何工作,因为我刚接触春季批次可能会犯一些错误。我尝试了一些示例中的以下代码,但它不起作用。我是否必须写一些其他课程?
<bean id="itemWriter" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<!-- Why CDATA?
because < etc. is not allowed for xml values
when you use < xml parser will work, but
now the sql won't because of the & spring assumes
a placeholder, see
- AbstractSqlPagingQueryProvider.init(...)
- JdbcParameterUtils.countParameterPlaceholders(...)
-->
<value>
<![CDATA[
DELETE FROM TEST
WHERE id = ?
and sub.id = ?
and ...
]]>
</value>
</property>
<property name="itemPreparedStatementSetter">
<bean class="...FieldSetItemPreparedStatementSetter" />
</property>
</bean>
ItemPreparedStatementSetter
/**
* Implementation for {@link ItemPreparedStatementSetter},
* sets the values from {@link FieldSet}.
*
*/
public class FieldSetItemPreparedStatementSetter implements ItemPreparedStatementSetter<FieldSet> {
/** {@inheritDoc} */
@Override
public void setValues(FieldSet item, PreparedStatement ps) throws SQLException {
for (int i = 0; i < item.getValues().length; i++) {
// PreparedStatements start with 1
ps.setObject(i + 1, item.getValues()[i]);
}
}
}
我的错误是: -
Encountered an error executing the step
java.lang.ClassCastException: com.mkyong.User cannot be cast to org.springframework.batch.item.file.transform.FieldSet
at com.mkyong.FieldSetItemPreparedStatementSetter.setValues(FieldSetItemPreparedStatementSetter.java:1)
at org.springframework.batch.item.database.JdbcBatchItemWriter$1.doInPreparedStatement(JdbcBatchItemWriter.java:190)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:589)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)
at org.springframework.batch.item.database.JdbcBatchItemWriter.write(JdbcBatchItemWriter.java:186)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:175)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:151)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:274)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:199)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:395)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:131)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:137)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:131)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:127)
at com.mkyong.App.run(App.java:34)
at com.mkyong.App.main(App.java:16)
Dec 06, 2013 3:50:56 PM org.springframework.batch.core.launch.support.SimpleJobLauncher$1 run
INFO: Job: [FlowJob: [name=testJob]] completed with the following parameters: [{}] and the following status: [FAILED]
Exit Status : FAILED
Exit Status : [java.lang.ClassCastException: com.mkyong.User cannot be cast to org.springframework.batch.item.file.transform.FieldSet]
Done
答案 0 :(得分:2)
代码已“正式更正”,但您必须使用ItemPreparedStatementSetter
而不是User
声明FieldSet
,因为ItemWriter
使用{{1}创建的同一对象}};我想你的读者会返回ItemReader
类型的对象。
根据新的通用有界类型替换为User
和ItemPreparedStatementSetter<User>
。
答案 1 :(得分:0)
也许,您的问题解释缺少一些信息,但在步骤定义中,您必须授予读取时返回的对象的匹配并传递给编写器。更好的解释:
阅读并创建一个MyCustomInputPOJO:
public class MyCustomFieldSetMapper implements FieldSetMapper<MyCustomInputPOJO> {
@Override
public MyCustomPOJO mapFieldSet(FieldSet fs) throws BindException {
MyCustomInputPOJO pojo = new MyCustomInputPOJO();
pojo.setAnAttribute(fs.readString("anAttribute"));
return pojo;
}
}
将MyCustomInputPOJO传递给处理器(如果有),并转换为MyCustomOutputPOJO:
@Component("MyProcessor")
public class MyCustomProcessor implements ItemProcessor<MyCustomInputPOJO, MyCustomOutputPOJO> {
public MyCustomOutputPOJO doProcess(MyCustomInputPOJO input) {
MyCustomOutputPOJO output = ConverterLogic.convert(input);
return output
}
}
现在你必须将MyCustomOutputPOJO传递给JdbcBatchItemWriter使用的ItemPreparedStatementSetter实现:
public class MyCustomItemPreparedStatementSetter implements ItemPreparedStatementSetter<MyCustomOutputPOJO> {
public void setValues(MyCustomOutputPOJO output, PreparedStatement ps) throws SQLException {
ps.setString(1, output.getAnAttribute());
}
}
您的步骤配置:
<job id="MyJob">
<step id="lerArquivoSaldos" >
<tasklet>
<chunk
reader="MyReader"
processor = "MyProcessor"
writer="MyWriter"
commit-interval="10"
>
</chunk>
</tasklet>
</step>
</job>
其中MyReader和MyProcessor是分别引用MyCustomFieldSetMapper和MyCustomItemPreparedStatementSetter的自定义bean。
答案 2 :(得分:0)
public class FieldSetItemPreparedStatementSetter implements ItemPreparedStatementSetter<com.mkyong.User > {
/** {@inheritDoc} */
@Override
public void setValues(com.mkyong.User item, PreparedStatement ps) throws SQLException {
for (int i = 0; i < item.getValues().length; i++) {
// PreparedStatements start with 1
ps.setObject(i + 1, item.getValues()[i]);
}
}
}
将FieldSet
类替换为com.mkyong.User
abd,分别更改setter / getter。