在使用Spring Batch的拆分作业中,Marshaller必须支持编组对象错误的类

时间:2018-08-24 13:23:30

标签: java spring spring-batch

在我用来学习的Spring批处理应用程序中,该应用程序是从数据库表中读取并保存为xml文件。我试图拆分步骤,以便2个步骤并行运行(流)。相关代码(如果您需要更多详细信息,我会添加它们)。当我运行作业时,它会读取每个step1和step2的前10条记录,但是每读取10条记录后都会出现错误:java.lang.IllegalStateException:编组人员必须支持编组对象的类

jobPerson.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:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc">

.
.


    <bean id="processWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
           <property name="resource" value="file:xml/process.xml"/>
           <property name="marshaller"  ref="processMarshaller"/>
           <property name="rootTagName" value="process"/>
        </bean>



        <bean id="processPersonWriter" class="org.springframework.batch.item.xml.StaxEventItemWriter">
           <property name="resource" value="file:xml/processPerson.xml"/>
           <property name="marshaller"  ref="processPersonMarshaller"/>
           <property name="rootTagName" value="processPerson"/>
        </bean>

        <bean id="personMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
           <property name="classesToBeBound">
              <value>sb.dbToxml.Person </value>
           </property>
        </bean>
        <bean id="processMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
          <property name="classesToBeBound">
            <value>sb.dbToxml.Process</value>
          </property>
        </bean>
        <bean id="processPersonMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller" >
           <property name="classesToBeBound">
             <value>sb.marshaller.ProcessPerson</value>
           </property>
        </bean>
    <bean id="processReader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
            <property name="dataSource" ref="dataSource"/>
            <property name="sql" value="SELECT CRA_PROCESS_ID,FEED_PROCESS_TYPE_CD from CRA_PROCESS  "></property>
            <property name="rowMapper">
              <bean class="sb.mappers.ProcessMapper">

              </bean>
            </property>
        </bean>

        <bean id="processPersonReader" class="org.springframework.batch.item.database.JdbcCursorItemReader">
          <property name="dataSource" ref="dataSource"></property>
          <property name="sql" value="SELECT cra_process_person_id, sin FROM Cra_Process_Person WHERE cra_process_id &lt; 400"></property>
          <property name="rowMapper">
            <bean  class="sb.mappers.ProcessPersonMapper"></bean>
          </property>
        </bean>


        <!--  ce qui suit pour un job avec  chunk -->
         <batch:job id="personJob">
        <batch:split id="split1" next="step11">
            <batch:flow>
                <batch:step id="step1A1">
                    <batch:tasklet
                        transaction-manager="transactionManager">
                        <batch:chunk reader="processReader"
                            writer="processWriter" commit-interval="10"></batch:chunk>
                    </batch:tasklet>
                </batch:step>
            </batch:flow>
            <batch:flow>
                <batch:step id="step1B1">
                    <batch:tasklet
                        transaction-manager="transactionManager">
                        <batch:chunk reader="processPersonReader"
                            writer="processPersonWriter" commit-interval="10"></batch:chunk>
                    </batch:tasklet>
                </batch:step>
            </batch:flow>
        </batch:split>

        <batch:step id="step11">
            <batch:tasklet transaction-manager="transactionManager">
                <batch:chunk reader="itemReader" writer="itemWriter"
                    commit-interval="30">
                    <batch:listeners>
                        <batch:listener ref="chunkPersonListener" />
                    </batch:listeners>
                </batch:chunk>
            </batch:tasklet>
            <batch:listeners>
                <batch:listener ref="personReadListener" />
            </batch:listeners>
        </batch:step>
        <batch:listeners>
            <batch:listener ref="jobPersonListener" />
        </batch:listeners>
    </batch:job>

</beans>

processMapper:

package sb.mappers;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import ca.gc.cfp.model.entity.process.CraProcess;

public class ProcessMapper implements RowMapper<CraProcess>
{

  @Override
  public CraProcess mapRow(ResultSet rs, int arg1) throws SQLException
  {
    CraProcess craProcess =new CraProcess();
    craProcess.setCraProcessId(rs.getLong("Cra_Process_Id"));
    craProcess.setFeedProcessTypeCd(rs.getShort("feed_Process_Type_Cd"));
    System.out.println("process Mapper id : "+craProcess.getCraProcessId()+" feed type cd  :"+craProcess.getFeedProcessTypeCd());
    return craProcess;
  }

}

ProcessPersonMapper:

package sb.mappers;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import ca.gc.cfp.model.entity.process.CraProcessPerson;

public class ProcessPersonMapper implements RowMapper<CraProcessPerson>
{

  @Override
  public CraProcessPerson mapRow(ResultSet rs, int arg1) throws SQLException
  {
    CraProcessPerson craProcessPerson=new CraProcessPerson();
    craProcessPerson.setCraProcessPersonId(rs.getLong("cra_process_person_id"));
    craProcessPerson.setSin(rs.getString("sin"));
    System.out.println("process Person  Mapper id : "+craProcessPerson.getCraProcessPersonId()+" Sin   :"+craProcessPerson.getSin());

    return craProcessPerson;
  }

}

Process.java:

package sb.dbToxml;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="process")
public class Process
{

  long cra_process_id;
  int feed_process_id;

  @XmlElement(name="processId")
  public long getCra_process_id()
  {
    return cra_process_id;
  }
  public void setCra_process_id(long cra_process_id)
  {
    this.cra_process_id = cra_process_id;
  }
  @XmlElement(name="feedProcess")
  public int getFeed_process_id()
  {
    return feed_process_id;
  }
  public void setFeed_process_id(int feed_process_id)
  {
    this.feed_process_id = feed_process_id;
  }

}

ProcessPerson.java:

package sb.marshaller;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="processPerson")
public class ProcessPerson
{
  long cra_process_id ;
  String Sin;
  @XmlElement(name="craProcessId")
  public long getCra_process_id()
  {
    return cra_process_id;
  }
  public void setCra_process_id(long cra_process_id)
  {
    this.cra_process_id = cra_process_id;
  }
  @XmlElement(name="sin")
  public String getSin()
  {
    return Sin;
  }
  public void setSin(String sin)
  {
    Sin = sin;
  }


}

1 个答案:

答案 0 :(得分:1)

processReader配置有行映射器sb.mappers.ProcessMapper。该映射器返回类型为CraProcess的项目。但是,processWriter配置了processMarshaller,该项目需要sb.dbToxml.Process类型的项目。因此,读取器和写入器之间存在类型不匹配。所以:

  • 您的ProcessMapper应该返回Process(而不是CraProcess
  • 或者您的processMarshaller应该期望使用CraProcess类型的商品(而不是Process

您在processPersonReaderprocessPersonWriter上遇到同样的问题。