如何从春季批次中的3个表中读取关系数据

时间:2016-08-31 12:58:11

标签: java spring spring-batch

我需要从3个表(CONTRACT,LANE,RATE)读取数据。合同可以是多个,并且对于每个合同,我可以有多个LANE,对于每个LANE,我可以有多个RATE。表有外键关系。

我想从表中读取数据并以相关方式设置为Java Objects。 Java POJO就像。

  public class Contract extends TICSection {

    private RTRate rtRate;

    private List<Lane> lanes = new ArrayList<Lane>();

    private String effectiveDate;
    private String expirationDate;
    private String contractNumber;
    private String contractTitle;
  }

public class Lane extends TICSection {  

private List<Rate> rate = new ArrayList<Rate>();
private String laneNumber ;

private String laneId ;
private String opFlag ;

private String depCntry ;
private String destCntry;
}   

public class Rate extends TICSection {

private String priceComponent ;
private String price ;

private String currency ;
private String quantityUnit ;

private String priceUnit ;
}   

在java对象合同中我有车道列表,在车道我有费率列表。我想要这种格式的3个相应表中的所有数据。

请帮助我如何使用ItemReader以此格式设置数据。

此外,如果我在我的上下文xml中设置 commit-interval = 10 ,我怎样才能确保spring批量读取和处理一次仅1个Contract和10 Lane。有可能吗?

问题是我正在尝试从3个不同的表中读取数据,并且我想以类似的方式将它们映射到Java对象。像合同具有与其关联的通道列表和具有与其关联的费率列表的通道。因此,当我处理记录时,我得到所有相关的通道和费率数据。

对于1个表格,我的配置如下所示

<bean id="pagingItemReader"
    class="org.springframework.batch.item.database.JdbcPagingItemReader"
    scope="step">
    <property name="dataSource" ref="dataSource" />
    <property name="queryProvider">
        <bean
            class="org.springframework.batch.item.database.support.SqlPagingQueryProviderFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="selectClause" value="*" />
            <property name="fromClause" value="from gtn_lineitem" />
            <property name="whereClause" value="record_status in ('O','E') and contract_seq = :contractSeq" />
            <property name="sortKey" value="contract_seq" />
        </bean>
    </property>
    <!-- Inject via the ExecutionContext in rangePartitioner -->
    <property name="parameterValues">
      <map>
        <entry key="contractSeq" value="#{stepExecutionContext[contractSeq]}"/>
        <entry key="fromId" value="#{stepExecutionContext[fromId]}" />
        <entry key="toId" value="#{stepExecutionContext[toId]}" />
      </map>
    </property>
    <property name="pageSize" value="#{stepExecutionContext[laneCount]}" />
    <property name="rowMapper">
        <bean class="com.cat.srr.gtn.dao.mapper.GTNContractRowMapper" />
    </property>
</bean>


<!-- Actual Job -->


<bean id="contractReadPartitioner" class="com.cat.srr.gtn.batch.partitioner.ContractReadPartitioner">
    <property name="contractDao" ref="contractDao"></property>
</bean>
<bean id="taskExecutor" class="org.springframework.core.task.SyncTaskExecutor" />
<bean id="contractProcessor" class="com.cat.srr.gtn.batch.ContractProcessor" scope="step">
    <property name="threadName" value="#{stepExecutionContext[name]}"></property>
</bean>


<batch:job id="partitionJob" xmlns="http://www.springframework.org/schema/batch">
    <batch:step id="masterStep">
        <batch:partition step="slaveStep" partitioner="contractReadPartitioner">
            <batch:handler grid-size="1" task-executor="taskExecutor"/>
        </batch:partition>
    </batch:step>
    <batch:listeners>
        <batch:listener ref="jobListener" />
    </batch:listeners>
</batch:job>

 <batch:step id="slaveStep">
        <batch:tasklet transaction-manager="transactionManager">
            <batch:chunk reader="pagingItemReader" writer="contractWriter"
                processor="contractProcessor" commit-interval="1" />
        </batch:tasklet>
 </batch:step>

但是如果为3个不同的表声明3个读者如何将数据合并到java对象中。 要么 如果我编写连接查询以选择所有相关数据,那么Row Mapper将如何合并结果。什么是正确的方法。

public class GTNContractRowMapper implements RowMapper<GTNContract>{

@Override
public GTNContract mapRow(ResultSet rs, int arg1) throws SQLException {
    GTNContract contract = new GTNContract();
    contract.setContractSeq(rs.getString("CONTRACT_SEQ"));
    contract.setContractNumber(rs.getString("GTN_CONTRACT_ID"));
    contract.setContractTitle(rs.getString("CONTRACT_ID"));
    contract.setCarrierName(rs.getString("CARRIER_NAME"));
    contract.setCarrierSCAC(rs.getString("CARRIER_SCAC"));
    contract.setModeName(rs.getString("MODE_NM"));
    contract.setEffectiveDate(rs.getString("TERM_BEGIN"));
    contract.setExpirationDate(rs.getString("TERM_END"));


    return contract;
}

}

1 个答案:

答案 0 :(得分:2)

实际上我也需要处理器和写入器的信息。根据这些信息,我可以给出适当的解决方案。

但是根据您提供的读者信息,我想采用以下两种方法

:一种。 无自定义阅读器 1.分包商将在合同层面处理。 2.读者将根据每个合同读取LANE信息。 3.处理器将根据每个合同和 lane 获得RATE信息

因此,在处理器级别,我们有每个合同/车道/费率。

我正等待处理器和作者提供更多信息,以提供准确的方法。

<强> B中。 自定义阅读器 自定义的一个,您可以使用查询来构建自己的逻辑,该查询使用GROUP BY子句连接3个表。从Java开始,循环结果集并构建Contract对象。

谢谢, Nghia酒店