Выполнение запроса внутри пакетного процессора spring

#java #spring #jdbc #spring-batch

Вопрос:

В моем проекте мне нужно выполнить запрос внутри пакетного процессора Spring, чтобы проверить какое-либо поле.

Как я могу это сделать?

ИЗМЕНИТЬ: Добавление источников:

Это определение шага:

 @Bean
public Step step1(JdbcBatchItemWriter<CaricoDTO> step1Writer) {
    return stepBuilderFactory.get("step1").<CaricoDTO, CaricoDTO>chunk(10).reader(multiResourceItemReader())
            .processor(processorStep1()).writer(step1Writer).build();

}
 

Это определение multiResourceItemReader :

 @Bean
public MultiResourceItemReader<CaricoDTO> multiResourceItemReader() {
    MultiResourceItemReader<CaricoDTO> resourceItemReader = new MultiResourceItemReader<CaricoDTO>();
    ArrayList<Integer> indexesToRemove = new ArrayList<Integer>();
    Resource[] inputResources = null;
    PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
    try {
        inputResources = patternResolver.getResources(inputPath);
    } catch (IOException e) {
        e.printStackTrace();
    }

    resourceItemReader.setResources(inputResources);
    resourceItemReader.setDelegate(step1Reader());
    resourceItemReader.setComparator(new FileComparator());
    return resourceItemReader;
}
 

Это step1Reader :

 @Bean
public FlatFileItemReader<CaricoDTO> step1Reader() {
    FlatFileItemReader<CaricoDTO> reader = new FlatFileItemReader<CaricoDTO>();
    reader.setLinesToSkip(1);
    reader.setLineMapper(new DefaultLineMapper<CaricoDTO>() {
        {
            setLineTokenizer(new DelimitedLineTokenizer("|") {
                {
                    setNames(new String[] { ..... });
                }
            });
            setFieldSetMapper(new BeanWrapperFieldSetMapper<CaricoDTO>() {
                {
                    setTargetType(CaricoDTO.class);
                }
            });
        }
    });
    return reader;
}
 

Это мой процессор.:

 @Bean
public CaricoDTOItemProcessorStep1 processorStep1() {
    CaricoDTOItemProcessorStep1 processorStep1 = new CaricoDTOItemProcessorStep1();
    return processorStep1;
}
 

Это мое определение процессора:

 public class CaricoDTOItemProcessorStep1 implements ItemProcessor<CaricoDTO, CaricoDTO> {

    private String fileName;
    private static final Logger log = LoggerFactory.getLogger(CaricoDTOItemProcessorStep1.class);
    
    @Override
    public CaricoDTO process(CaricoDTO carico) throws Exception {

        carico.setDataCaricamento(new Date(System.currentTimeMillis()));
        carico.setFileName(carico.getResource().getFilename());
        return carico;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

}
 

А это мой писатель:

 @Bean
public JdbcBatchItemWriter<CaricoDTO> step1Writer(DataSource dataSource) {
    return new JdbcBatchItemWriterBuilder<CaricoDTO>()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql(....)
            .dataSource(dataSource).build();
}
 

Комментарии:

1. Что вы сделали до сих пор? Как выглядит ваш проект / настройка компонентов? Простым и понятным способом было бы использовать JdbcTemplate , но могут быть и другие / лучшие способы сделать это.

2. @tmarwen У меня есть считыватель, считывающий из csv-файла, процессор и писатель, записывающий в бд, но мне приходится отбрасывать некоторые записи из-за значений, отсутствующих в таблицах домена. Я использую h2 в качестве сохранения данных

3.Я все еще не понимаю общей картины. Не могли бы вы добавить минимальный воспроизводимый код из своей базы кода? Как вы уже выполняете чтение / запись, используете пакет Spring ItemReader / ItemWriter ?

4. @tmarwen Я добавил информацию к своему вопросу.

Ответ №1:

Учитывая небольшие детали в основной операции, я предполагаю, что общее решение будет принято.

Учитывая классическую настройку пакетного проекта Spring, у вас должен быть доступ к org.springframework.jdbc.core.JdbcTemplate компоненту, подключенному к цели javax.sql.DataSource , который вы можете просто ввести в один из компонентов вашего пакетного сотрудника:

  • org.springframework.batch.item.ItemReader
  • org.springframework.batch.item.ItemWriter
  • org.springframework.batch.item.ItemProcessor

Предполагая, что вам нужно выполнить некоторую проверку, прежде чем приступить к обработке элемента (и, возможно, отказаться от него), вы можете ввести JdbcTemplate компонент, выполнить запрос для проверки инвариантов модели, а затем выполнить соответствующие действия:

 public class CaricoDTOItemProcessorStep1 implements ItemProcessor<CaricoDTO, CaricoDTO> {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;

    private String fileName;
    
    private static final Logger log = LoggerFactory.getLogger(CaricoDTOItemProcessorStep1.class);
    
    @Override
    public CaricoDTO process(CaricoDTO item) throws Exception {
        boolean someValue = jdbcTemplate.queryForObject("SELECT some_field FROM some_table WHERE some_other_field = 0", (rs, rowNum) -> rs.getBoolean(0));
        if (someValue) {
            carico.setDataCaricamento(new Date(System.currentTimeMillis()));
            carico.setFileName(carico.getResource().getFilename());
            return carico;
        } else {
            return null; // causes the item to be discarded from processing
        }
    }
}
 

Излишне говорить, что ваш запрос будет зависеть от варианта использования вашего домена и нуждается в обновлении.

Комментарии:

1. Большое спасибо. Я проверю ваше решение.

2. Спасибо. Это решило мою проблему!