问题描述
我正在开发Spring Batch CompositeItemReader and Writter
示例.在此程序中,我试图从mysql db表中读取两个表的数据,并写入单个XML文件.尝试执行此操作时,我看到以下错误即将出现:
I am developing Spring Batch CompositeItemReader and Writter
example. In this program I am trying to read data two tables from mysql db table and write to single XML file. When trying to do that I see following error is coming:
java.lang.ClassCastException: java.lang.String cannot be cast to com.common.batch.model.Customer
at com.common.batch.processor.CustomerProcessor.process(CustomerProcessor.java:1)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess(SimpleChunkProcessor.java:126)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.transform(SimpleChunkProcessor.java:293)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:192)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271)
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:257)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:198)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
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:67)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:162)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:141)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:304)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128)
at com.common.batch.main.CompositeXMLMain.main(CompositeXMLMain.java:24)
我没有解决此问题的任何线索.请引导我.Employee.java
I don't have any clue in solving this issue. Please guide me.Employee.java
public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
private Integer employeeNumber;
private String lastName;
private String firstName;
private String extension;
private String email;
private String officeCode;
private Integer reportsTo;
private String jobTitle;
// setters and getters
@Override
public String toString() {
return customerNumber + "|" + customerName + "|" + contactLastName + "|" + contactFirstName + "|" +
phone+ "|" + addressLine1 + "|" + addressLine2 + "|" + city + "|" + state+ "|" + postalCode + "|" +
country+ "|" + salesRepEmployeeNumber + "|" + creditLimit;
}
}
Customer.java
Customer.java
public class Customer implements Serializable{
private static final long serialVersionUID = 1L;
private Integer customerNumber;
private String customerName;
private String contactLastName;
private String contactFirstName;
private String phone;
private String addressLine1;
private String addressLine2;
private String city;
private String state;
private String postalCode;
private String country;
private Integer salesRepEmployeeNumber;
private Double creditLimit;
// setters and getters
@Override
public String toString() {
return employeeNumber + "|"+ lastName + "|" + firstName + "|"+ extension +
"|" + email + "|" + officeCode+ "|" + reportsTo + "|" + jobTitle;
}
}
xml-jdbc-composite-item-reader-job.xml
xml-jdbc-composite-item-reader-job.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<import resource="classpath:context-datasource.xml" />
<!-- JobRepository and JobLauncher are configuration/setup classes -->
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" />
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<!-- Step will need a transaction manager -->
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<!-- =========================================================== -->
<job id="compositeJdbcReaderJob" xmlns="http://www.springframework.org/schema/batch">
<step id="compositeJdbcReaderStep" next="compositeJdbcReaderStep2">
<tasklet>
<chunk reader="compositeItemReader1" writer="itemWriter1" processor="itemCustomerProcessor"
commit-interval="5" />
</tasklet>
</step>
<step id="compositeJdbcReaderStep2">
<tasklet>
<chunk reader="compositeItemReader2" writer="itemWriter2" processor="itemEmployeeProcessor"
commit-interval="5" />
</tasklet>
</step>
</job>
<!-- ============= Composite Item Reader ================ -->
<bean id="compositeItemReader1" class="com.common.batch.reader.CompositeCursorItemReader">
<property name="unifyingMapper">
<bean class="com.common.batch.mapper.DefaultUnifyingStringItemsMapper" />
</property>
<property name="cursorItemReaders">
<list>
<ref bean="itemReader1" />
</list>
</property>
</bean>
<bean id="compositeItemReader2" class="com.common.batch.reader.CompositeCursorItemReader">
<property name="unifyingMapper">
<bean class="com.common.batch.mapper.DefaultUnifyingStringItemsMapper" />
</property>
<property name="cursorItemReaders">
<list>
<ref bean="itemReader2" />
</list>
</property>
</bean>
<!-- ========== ItemReader =============== -->
<bean id="itemReader1" class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="saveState" value="true" />
<property name="sql">
<value>
<![CDATA[ ${select.sql.customers} ]]>
</value>
</property>
<property name="rowMapper">
<bean class="com.common.batch.mapper.CustomerMapper" />
</property>
</bean>
<bean id="itemReader2" class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="saveState" value="true" />
<property name="sql">
<value>
<![CDATA[ ${select.sql.employees} ]]>
</value>
</property>
<property name="rowMapper">
<bean class="com.common.batch.mapper.EmployeeMapper" />
</property>
</bean>
<!-- ItemWritter -->
<bean id="itemWriter1" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/customers.xml" />
<property name="marshaller" ref="customerUnmarshaller" />
<property name="rootTagName" value="customers" />
</bean>
<bean id="itemWriter2" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/customers.xml" />
<property name="marshaller" ref="employeeUnmarshaller" />
<property name="rootTagName" value="employees" />
</bean>
<!-- ======= Employee Unmarshaller ======== -->
<bean id="employeeUnmarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="employee" value="com.common.batch.model.Employee" />
</util:map>
</property>
</bean>
<!-- ======= Customer Unmarshaller ======== -->
<bean id="customerUnmarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="customer" value="com.common.batch.model.Customer" />
</util:map>
</property>
</bean>
<bean id="itemCustomerProcessor" class="com.common.batch.processor.CustomerProcessor" />
<bean id="itemEmployeeProcessor" class="com.common.batch.processor.EmployeeProcessor" />
</beans>
CompositeXMLMain.java
CompositeXMLMain.java
public class CompositeXMLMain {
@SuppressWarnings("resource")
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("composite/xml-jdbc-composite-item-reader-job.xml");
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("compositeJdbcReaderJob");
JobExecution execution;
try {
execution = jobLauncher.run(job, new JobParameters());
System.out.println("Job Exit Status : "+ execution.getStatus());
} catch (JobExecutionAlreadyRunningException | JobRestartException
| JobInstanceAlreadyCompleteException | JobParametersInvalidException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println("Done !!");
}
}
CustomerProcessor.java
Edit-1:CustomerProcessor.java
public class CustomerProcessor implements ItemProcessor<Customer, Customer>{
@Override
public Customer process(Customer result) throws Exception {
System.out.println("Processing result :"+result);
return result;
}
}
EmployeeProcessor.java
EmployeeProcessor.java
public class EmployeeProcessor implements ItemProcessor<Employee, Employee>{
@Override
public Employee process(Employee result) throws Exception {
System.out.println("Processing result :"+result);
return result;
}
}
CustomerMapper.java
Edit-2:CustomerMapper.java
public class CustomerMapper implements RowMapper<Customer>{
@Override
public Customer mapRow(ResultSet rs, int rowNum) throws SQLException {
Customer customer = new Customer();
customer.setCustomerNumber(rs.getInt("customerNumber"));
customer.setCustomerName(rs.getString("customerName"));
customer.setContactLastName(rs.getString("contactLastName"));
customer.setContactFirstName(rs.getString("contactFirstName"));
customer.setPhone(rs.getString("phone"));
customer.setAddressLine1(rs.getString("addressLine1"));
customer.setAddressLine2(rs.getString("addressLine2"));
customer.setCity(rs.getString("city"));
customer.setState(rs.getString("state"));
customer.setPostalCode(rs.getString("postalCode"));
customer.setCountry(rs.getString("country"));
customer.setSalesRepEmployeeNumber(rs.getInt("salesRepEmployeeNumber"));
customer.setCreditLimit(rs.getDouble("creditLimit"));
return customer;
}
}
EmployeeMapper.java
EmployeeMapper.java
public class EmployeeMapper implements RowMapper<Employee>{
@Override
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
Employee employee = new Employee();
employee.setEmployeeNumber(rs.getInt("employeeNumber"));
employee.setLastName(rs.getString("lastName"));
employee.setFirstName(rs.getString("firstName"));
employee.setExtension(rs.getString("extension"));
employee.setEmail(rs.getString("email"));
employee.setOfficeCode(rs.getString("officeCode"));
employee.setReportsTo(rs.getInt("reportsTo"));
employee.setJobTitle(rs.getString("jobTitle"));
return employee;
}
}
我看到以下几个问题:
- 我看到下面显示了非常奇怪的XML输出
- 我只得到第二个数据库表数据,而第一个表数据被覆盖
XML输出?
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<string>1002|Murphy|Diane|x5800|[email protected]|1|0|President</string>
<string>1056|Patterson|Mary|x4611|[email protected]|1|1002|VP Sales</string>
<string>1076|Firrelli|Jeff|x9273|[email protected]|1|1002|VP Marketing</string>
<string>1088|Patterson|William|x4871|[email protected]|6|1056|Sales Manager (APAC)</string>
<string>1102|Bondur|Gerard|x5408|[email protected]|4|1056|Sale Manager (EMEA)</string>
<string>1143|Bow|Anthony|x5428|[email protected]|1|1056|Sales Manager (NA)</string>
<string>1165|Jennings|Leslie|x3291|[email protected]|1|1143|Sales Rep</string>
<string>1166|Thompson|Leslie|x4065|[email protected]|1|1143|Sales Rep</string>
<string>1188|Firrelli|Julie|x2173|[email protected]|2|1143|Sales Rep</string>
<string>1216|Patterson|Steve|x4334|[email protected]|2|1143|Sales Rep</string>
<string>1286|Tseng|Foon Yue|x2248|[email protected]|3|1143|Sales Rep</string>
<string>1323|Vanauf|George|x4102|[email protected]|3|1143|Sales Rep</string>
<string>1337|Bondur|Loui|x6493|[email protected]|4|1102|Sales Rep</string>
<string>1370|Hernandez|Gerard|x2028|[email protected]|4|1102|Sales Rep</string>
<string>1401|Castillo|Pamela|x2759|[email protected]|4|1102|Sales Rep</string>
<string>1501|Bott|Larry|x2311|[email protected]|7|1102|Sales Rep</string>
<string>1504|Jones|Barry|x102|[email protected]|7|1102|Sales Rep</string>
<string>1611|Fixter|Andy|x101|[email protected]|6|1088|Sales Rep</string>
<string>1612|Marsh|Peter|x102|[email protected]|6|1088|Sales Rep</string>
<string>1619|King|Tom|x103|[email protected]|6|1088|Sales Rep</string>
<string>1621|Nishi|Mami|x101|[email protected]|5|1056|Sales Rep</string>
<string>1625|Kato|Yoshimi|x102|[email protected]|5|1621|Sales Rep</string>
<string>1702|Gerard|Martin|x2312|[email protected]|4|1102|Sales Rep</string>
</employees>
我已更正
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<import resource="classpath:context-datasource.xml" />
<!-- JobRepository and JobLauncher are configuration/setup classes -->
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean" />
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<!-- Step will need a transaction manager -->
<bean id="transactionManager"
class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
<!-- =========================================================== -->
<job id="compositeJdbcReaderJob" xmlns="http://www.springframework.org/schema/batch">
<step id="compositeJdbcReaderStep" next="compositeJdbcReaderStep2">
<tasklet>
<chunk reader="compositeItemReader1" writer="itemWriter1" commit-interval="5" />
</tasklet>
</step>
<step id="compositeJdbcReaderStep2">
<tasklet>
<chunk reader="compositeItemReader2" writer="itemWriter2" commit-interval="5" />
</tasklet>
</step>
</job>
<!-- ============= Composite Item Reader ================ -->
<bean id="compositeItemReader1" class="com.common.batch.reader.CompositeCursorItemReader">
<property name="unifyingMapper">
<bean class="com.common.batch.mapper.DefaultUnifyingStringItemsMapper" />
</property>
<property name="cursorItemReaders">
<list>
<ref bean="itemReader1" />
</list>
</property>
</bean>
<bean id="compositeItemReader2" class="com.common.batch.reader.CompositeCursorItemReader">
<property name="unifyingMapper">
<bean class="com.common.batch.mapper.DefaultUnifyingStringItemsMapper" />
</property>
<property name="cursorItemReaders">
<list>
<ref bean="itemReader2" />
</list>
</property>
</bean>
<!-- ========== ItemReader =============== -->
<bean id="itemReader1" class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="saveState" value="true" />
<property name="sql">
<value>
<![CDATA[ ${select.sql.customers} ]]>
</value>
</property>
<property name="rowMapper">
<bean class="com.common.batch.mapper.CustomerMapper" />
</property>
</bean>
<bean id="itemReader2" class="org.springframework.batch.item.database.JdbcCursorItemReader">
<property name="dataSource" ref="dataSource" />
<property name="saveState" value="true" />
<property name="sql">
<value>
<![CDATA[ ${select.sql.employees} ]]>
</value>
</property>
<property name="rowMapper">
<bean class="com.common.batch.mapper.EmployeeMapper" />
</property>
</bean>
<!-- ItemWritter -->
<bean id="itemWriter1" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/customers.xml" />
<property name="marshaller" ref="customerUnmarshaller" />
<property name="rootTagName" value="customers" />
</bean>
<bean id="itemWriter2" class="org.springframework.batch.item.xml.StaxEventItemWriter">
<property name="resource" value="file:xml/customers.xml" />
<property name="marshaller" ref="employeeUnmarshaller" />
<property name="rootTagName" value="employees" />
</bean>
<!-- ======= Employee Unmarshaller ======== -->
<bean id="employeeUnmarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="employee" value="com.common.batch.model.Employee" />
</util:map>
</property>
</bean>
<!-- ======= Customer Unmarshaller ======== -->
<bean id="customerUnmarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="aliases">
<util:map id="aliases">
<entry key="customer" value="com.common.batch.model.Customer" />
</util:map>
</property>
</bean>
<bean id="itemCustomerProcessor" class="com.common.batch.processor.CustomerProcessor" />
<bean id="itemEmployeeProcessor" class="com.common.batch.processor.EmployeeProcessor" />
</beans>
推荐答案
我不明白,如果无论如何每个都只使用一个阅读器,为什么要使用CompositeItemReaders
i do not understand, why you use CompositeItemReaders if you only use one reader for each, anyways
我猜你是从 github存储库?
源代码有:
public class DefaultUnifyingStringItemsMapper implements UnifyingItemsMapper<String> {
/** {@inheritDoc} */
@Override
public String mapItems(List<?> items) throws Exception {
if (items != null && items.size() > 0) {
StringBuilder sb = new StringBuilder();
for (Object item : items) {
if (item != null) {
sb.append(item);
}
}
if (sb.length() > 0) {
return sb.toString();
} else {
return null;
}
} else {
return null;
}
}
}
这就是问题所在,它只会创建一个大字符串,该字符串实际上是不是您想要的那种类型(在处理器和编写器中进行处理),现在它不能与需要该项目的处理器一起使用员工类型
so that is the problem, it will just create a big string which is or is not the kind of item you actually want (to process in processor and writer), right now it won't work with the processor which expects items of type Employee
如果您将更多阅读器添加到Compositeitemreader中,则需要重新考虑您的程序,尤其是编写器,他们将使用哪种项目?
if you add more readers to the compositeitemreaders, you need to rethink your program especially the writers, what kind of item will they use?
这篇关于java.lang.ClassCastException:无法将java.lang.String强制转换为com.common.batch.model.Customer-Spring Batch CompositeItemReader和Writter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!