Springbatch читает данные из двух таблиц БД и записывает в файл XML - PullRequest
0 голосов
/ 02 мая 2020

Я новичок в весенней партии, и я хотел бы получить некоторые рекомендации, пожалуйста, по проблеме, с которой я столкнулся. У меня есть две таблицы БД Settlement_Header (который содержит информацию заголовка файла) и Settlement_Detail (который представляет собой список всех транзакций для этого файла заголовка.)

Цель состоит в том, чтобы создать файл с 1 заголовком и несколько деталей.

Текущий вывод - заголовок появляется на каждой записи, и я хочу, чтобы он появлялся один раз. Я пытался включить условие в обработчик предметов, но это не помогло решить мою проблему.

Токовый выход

Требуемый выход

Желаемый Вывод

Это мой Itemreader

@Bean(destroyMethod="")
public JdbcCursorItemReader<Settlement> settlementreader(){
    JdbcCursorItemReader<Settlement> ItemReader = new JdbcCursorItemReader<>();
    ItemReader.setDataSource(dataSource);
    ItemReader.setSql("SELECT DISTINCT A.PROCESS_DATE,A.FILE_NAME,A.SERVICE,A.SUB_SERVICE,A.SENDER,A.RUN_MODE,A.CURRENCY,A.PROCESS_WINDOW_NO,B.RECORD_SEQ_NO,"
            + "B.AGENT_FROM,B.AGENT_TO,B.SETTLE_VOLUME,B.AMOUNT_CURRENCY,B.SETTLE_AMOUNT "
            + "FROM SETTLEMENT_HEADER A,SETTLEMENT_DETAIL B WHERE A.FILE_ID=B.FILE_ID");
    ItemReader.setRowMapper(new SettlementRowMapper());
    return ItemReader;
}

Writer

@Bean (destroyMethod="")
   public StaxEventItemWriter<Settlement> settlementwriter() throws Exception {
       StaxEventItemWriter<Settlement> ItemWriter = new StaxEventItemWriter<>();
       ItemWriter.setResource(new FileSystemResource(".../Settlement.xml")); 
       ItemWriter.setRootTagName("Settlement");
       ItemWriter.setMarshaller(marshaller);
       ItemWriter.afterPropertiesSet();
       return ItemWriter;
   }

Row Mapper

publi c Класс SettlementRowMapper реализует RowMapper {

@Override
public Settlement mapRow(ResultSet rs, int rowNum) throws SQLException {

    Settlement Settlement = new Settlement ();
    List<SettlementHeader> settlementheader= new ArrayList<SettlementHeader>();
    List<SettlementDetail> settlementdetail = new ArrayList<SettlementDetail>();
    SettlementHeader header = new SettlementHeader();
    SettlementDetail detail = new SettlementDetail();
    SttlAmt sttlAmt = new SttlAmt();


    header.setPrcDte(rs.getDate("PROCESS_DATE").toLocalDate());
    header.setFilename(rs.getString("FILE_NAME"));
    header.setService(rs.getString("SERVICE"));
    header.setSubServ(rs.getString("SUB_SERVICE"));
    header.setSender(rs.getInt("SENDER"));
    header.setRunMode(rs.getString("RUN_MODE"));
    header.setCurrency(rs.getString("CURRENCY"));
    header.setPrcWndwNum(rs.getInt("PROCESS_WINDOW_NO"));
    detail.setSeqNumb(rs.getInt("RECORD_SEQ_NO"));
    detail.setAgntFrm(rs.getInt("AGENT_FROM"));
    detail.setAgntTo(rs.getInt("AGENT_TO"));
    detail.setSttlVol(rs.getInt("SETTLE_VOLUME"));
    sttlAmt.setCcy(rs.getString("AMOUNT_CURRENCY"));
    sttlAmt.setValue(rs.getDouble("SETTLE_AMOUNT"));
    detail.setSttlAmt(sttlAmt); 
    settlementheader.add(header);
    settlementdetail.add(detail);
    Settlement.setSettlementDetails(settlementdetail);
    Settlement.setSettlementHeader(settlementheader);
    return Settlement;
}

1 Ответ

0 голосов
/ 02 мая 2020

Ваше поведение абсолютно нормальное, поскольку для каждого прочитанного вами предмета у вас есть объект урегулирования, который содержит один заголовок и одну деталь. Ваша проблема часто встречается в области пакетной обработки, а в Spring Batch она называется «Driving Query Based ItemReaders», вы можете найти больше информации об этом в здесь .

. Подходя к вашей проблеме, следуйте этому шаблону, создав читатель, который возвращает только SettlementHeader Предметы и добавляет процессор, который берет каждый Предмет ( SettlementHeader ) и преобразует его в Расчетный объект путем запроса базы данных для Сведения о расчете .

Вот мое решение:

Элементы шага

@Bean(destroyMethod = "")
public JdbcCursorItemReader<SettlementHeader> settlementHeaderReader(DataSource dataSource) {
    JdbcCursorItemReader<SettlementHeader> ItemReader = new JdbcCursorItemReader<>();
    ItemReader.setDataSource(dataSource);
    ItemReader.setSql("SELECT DISTINCT A.FILE_ID, A.PROCESS_DATE, A.FILE_NAME, A.SERVICE, A.SUB_SERVICE, A.SENDER, A.RUN_MODE, A.CURRENCY, A.PROCESS_WINDOW_NO"
                        + "FROM SETTLEMENT_HEADER A");
    ItemReader.setRowMapper(new SettlementHeaderRowMapper());
    return ItemReader;
}


@Bean
public ItemProcessor<SettlementHeader, Settlement> settlementHeaderProcessor(JdbcTemplate jdbcTemplate){

    return item -> {
        List<SettlementDetail> settlementDetails = jdbcTemplate.query("SELECT B.RECORD_SEQ_NO, B.AGENT_FROM,B.AGENT_TO,B.SETTLE_VOLUME,B.AMOUNT_CURRENCY,B.SETTLE_AMOUNT " +
                "  FROM SETTLEMENT_DETAIL B WHERE ? = B.FILE_ID",
                new Object[]{item.getFileId()},
                new SettlementDetailRowMapper());

        Settlement settlement = new Settlement ();

        List<SettlementHeader> settlementheader= new ArrayList<SettlementHeader>();
        settlementheader.add(item);

        settlement.setSettlementDetails(settlementDetails);
        settlement.setSettlementHeader(settlementheader);

        return settlement;
    };
}

// Your writer should stay the same
@Bean(destroyMethod = "")
public StaxEventItemWriter<Settlement> settlementwriter() throws Exception {
    StaxEventItemWriter<Settlement> ItemWriter = new StaxEventItemWriter<>();
    ItemWriter.setResource(new FileSystemResource(".../Settlement.xml"));
    ItemWriter.setRootTagName("Settlement");
    ItemWriter.setMarshaller(marshaller);
    ItemWriter.afterPropertiesSet();
    return ItemWriter;
}

Составители строк

public class SettlementHeaderRowMapper implements RowMapper<SettlementHeader> {
@Override
public SettlementHeader mapRow(ResultSet rs, int i) throws SQLException {
    SettlementHeader header = new SettlementHeader();

    header.setFileId(rs.getInt("FILE_ID"));
    header.setPrcDte(rs.getDate("PROCESS_DATE").toLocalDate());
    header.setFilename(rs.getString("FILE_NAME"));
    header.setService(rs.getString("SERVICE"));
    header.setSubServ(rs.getString("SUB_SERVICE"));
    header.setSender(rs.getInt("SENDER"));
    header.setRunMode(rs.getString("RUN_MODE"));
    header.setCurrency(rs.getString("CURRENCY"));
    header.setPrcWndwNum(rs.getInt("PROCESS_WINDOW_NO"));

    return header;
}

}

public class SettlementDetailRowMapper implements RowMapper<SettlementDetail> {
@Override
public SettlementDetail mapRow(ResultSet rs, int i) throws SQLException {
    SettlementDetail detail = new SettlementDetail();
    SttlAmt sttlAmt = new SttlAmt();

    detail.setSeqNumb(rs.getInt("RECORD_SEQ_NO"));
    detail.setAgntFrm(rs.getInt("AGENT_FROM"));
    detail.setAgntTo(rs.getInt("AGENT_TO"));
    detail.setSttlVol(rs.getInt("SETTLE_VOLUME"));
    sttlAmt.setCcy(rs.getString("AMOUNT_CURRENCY"));
    sttlAmt.setValue(rs.getDouble("SETTLE_AMOUNT"));
    detail.setSttlAmt(sttlAmt);

    return detail;
}

}

Надеюсь, это поможет вам.

...